Skip to content

Commit bdf9821

Browse files
cryptiklemurshuding
authored andcommittedNov 10, 2019
Adding initialData (#106)
* Adding initialData * Adding types to useSWRPages * flipping || * Adding test for initialData * Adding to readme * Requested changes
1 parent 8c2f988 commit bdf9821

File tree

5 files changed

+45
-27
lines changed

5 files changed

+45
-27
lines changed
 

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ const { data, error, isValidating, revalidate } = useSWR(key, fetcher, options)
114114
- `onSuccess`: callback function when a request finishs successfully
115115
- `onError`: callback function when a request returns an error
116116
- `onErrorRetry`: handler for [error retry](#error-retries)
117+
- `initialData`: initial data to be returned (note: This is per-hook)
117118

118119
When under a slow network (2G, <= 70Kbps), `errorRetryInterval` will be 10s, and
119120
`loadingTimeout` will be 5s by default.

‎src/types.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
export interface ConfigInterface<Data = any, Error = any> {
1+
export type fetcherFn<Data> = (...args: any) => Data | Promise<Data>
2+
export interface ConfigInterface<
3+
Data = any,
4+
Error = any,
5+
Fn extends fetcherFn<Data> = fetcherFn<Data>
6+
> {
27
errorRetryInterval?: number
38
loadingTimeout?: number
49
focusThrottleInterval?: number
@@ -8,8 +13,9 @@ export interface ConfigInterface<Data = any, Error = any> {
813
refreshWhenHidden?: boolean
914
revalidateOnFocus?: boolean
1015
shouldRetryOnError?: boolean
11-
fetcher?: any
16+
fetcher?: Fn
1217
suspense?: boolean
18+
initialData?: Data
1319

1420
onLoadingSlow?: (key: string, config: ConfigInterface<Data, Error>) => void
1521
onSuccess?: (

‎src/use-swr-pages.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ function App () {
8888
}
8989
*/
9090

91-
export function useSWRPages<OffsetType, Data, Error>(
91+
export function useSWRPages<OffsetType = any, Data = any, Error = any>(
9292
pageKey: string,
9393
pageFn: pageComponentType<OffsetType, Data, Error>,
9494
SWRToOffset: pageOffsetMapperType<OffsetType, Data, Error>,

‎src/use-swr.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import {
1818
triggerInterface,
1919
mutateInterface,
2020
broadcastStateInterface,
21-
responseInterface
21+
responseInterface,
22+
fetcherFn
2223
} from './types'
2324

2425
import defaultConfig, {
@@ -111,14 +112,14 @@ function useSWR<Data = any, Error = any>(
111112
): responseInterface<Data, Error>
112113
function useSWR<Data = any, Error = any>(
113114
key: keyInterface,
114-
fn?: Function,
115+
fn?: fetcherFn<Data>,
115116
config?: ConfigInterface<Data, Error>
116117
): responseInterface<Data, Error>
117118
function useSWR<Data = any, Error = any>(
118119
...args
119120
): responseInterface<Data, Error> {
120121
let _key: keyInterface,
121-
fn: Function | undefined,
122+
fn: fetcherFn<Data> | undefined,
122123
config: ConfigInterface<Data, Error> = {}
123124
if (args.length >= 1) {
124125
_key = args[0]
@@ -157,7 +158,7 @@ function useSWR<Data = any, Error = any>(
157158
const shouldReadCache = config.suspense || !useHydration()
158159

159160
// stale: get from cache
160-
let [data, setData] = useState(shouldReadCache ? cacheGet(key) : undefined)
161+
let [data, setData] = useState((shouldReadCache ? cacheGet(key) : undefined) || config.initialData)
161162
let [error, setError] = useState(
162163
shouldReadCache ? cacheGet(keyErr) : undefined
163164
)
@@ -322,7 +323,7 @@ function useSWR<Data = any, Error = any>(
322323
// and trigger a revalidation
323324

324325
const currentHookData = dataRef.current
325-
const latestKeyedData = cacheGet(key)
326+
const latestKeyedData = cacheGet(key) || config.initialData
326327

327328
// update the state if the key changed or cache updated
328329
if (

‎test/use-swr.test.tsx

+29-19
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
1-
import React, { Suspense, ReactNode, useState, useEffect } from 'react'
2-
import {
3-
cleanup,
4-
render,
5-
waitForDomChange,
6-
act,
7-
fireEvent
8-
} from '@testing-library/react'
1+
import { act, cleanup, fireEvent, render, waitForDomChange } from '@testing-library/react'
2+
import React, { ReactNode, Suspense, useEffect, useState } from 'react'
93

10-
import useSWR, { trigger, mutate, SWRConfig } from '../src'
4+
import useSWR, { mutate, SWRConfig, trigger } from '../src'
115

126
class ErrorBoundary extends React.Component<{ fallback: ReactNode }> {
137
state = { hasError: false }
@@ -188,39 +182,55 @@ describe('useSWR', () => {
188182
await act(() => new Promise(res => setTimeout(res, 100)))
189183
expect(container.textContent).toMatchInlineSnapshot(`"err err err"`)
190184
})
191-
185+
192186
it('should accept object args', async () => {
193187
const obj = { v: 'hello' }
194188
const arr = ['world']
195-
189+
196190
function Page() {
197191
const { data: v1 } = useSWR(
198192
['args-1', obj, arr],
199193
(a, b, c) => a + b.v + c[0]
200194
)
201-
195+
202196
// reuse the cache
203197
const { data: v2 } = useSWR(['args-1', obj, arr], () => 'not called!')
204-
198+
205199
// different object
206200
const { data: v3 } = useSWR(
207201
['args-2', obj, 'world'],
208202
(a, b, c) => a + b.v + c
209203
)
210-
204+
211205
return (
212206
<div>
213207
{v1}, {v2}, {v3}
214208
</div>
215209
)
216210
}
217-
const { container } = render(<Page />)
218-
211+
212+
const { container } = render(<Page/>)
213+
219214
await waitForDomChange({ container })
220215
expect(container.textContent).toMatchInlineSnapshot(
221216
`"args-1helloworld, args-1helloworld, args-2helloworld"`
222217
)
223218
})
219+
220+
it('should accept initial data', async () => {
221+
function Page() {
222+
const { data } = useSWR('initial-data-1', () => 'SWR', { initialData: 'Initial' })
223+
return <div>hello, {data}</div>
224+
}
225+
226+
const { container } = render(<Page/>)
227+
228+
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"hello, Initial"`)
229+
await waitForDomChange({ container }) // mount
230+
expect(container.firstChild.textContent).toMatchInlineSnapshot(
231+
`"hello, SWR"`
232+
)
233+
})
224234
})
225235

226236
describe('useSWR - refresh', () => {
@@ -625,14 +635,14 @@ describe('useSWR - suspense', () => {
625635

626636
it('should render multiple SWR fallbacks', async () => {
627637
function Section() {
628-
const { data: v1 } = useSWR(
638+
const { data: v1 } = useSWR<number>(
629639
'suspense-2',
630640
() => new Promise(res => setTimeout(() => res(1), 100)),
631641
{
632642
suspense: true
633643
}
634644
)
635-
const { data: v2 } = useSWR(
645+
const { data: v2 } = useSWR<number>(
636646
'suspense-3',
637647
() => new Promise(res => setTimeout(() => res(2), 100)),
638648
{
@@ -672,7 +682,7 @@ describe('useSWR - suspense', () => {
672682
expect(container.textContent).toMatchInlineSnapshot(`"hello"`)
673683
})
674684

675-
it.only('should throw errors', async () => {
685+
it('should throw errors', async () => {
676686
function Section() {
677687
const { data } = useSWR(
678688
'suspense-5',

0 commit comments

Comments
 (0)
Please sign in to comment.