From 0616f4b1160d4503a132df18e99a3928a20b086c Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 26 Nov 2019 14:22:20 +0800 Subject: [PATCH 1/6] fix the case that the arg array is empty --- src/libs/hash.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/hash.ts b/src/libs/hash.ts index 240f4bfcb..cab8eadb6 100644 --- a/src/libs/hash.ts +++ b/src/libs/hash.ts @@ -9,6 +9,7 @@ let counter = 0 // hashes an array of objects and returns a string export default function hash(args: any[]): string { + if (!args.length) return '' let key = 'arg' for (let i = 0; i < args.length; ++i) { let _hash From ab60acf4377c0e2e44ec269af88cf8b21a8add93 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 26 Nov 2019 14:35:45 +0800 Subject: [PATCH 2/6] fix hash primitive types --- src/libs/hash.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libs/hash.ts b/src/libs/hash.ts index cab8eadb6..066f9ad76 100644 --- a/src/libs/hash.ts +++ b/src/libs/hash.ts @@ -14,7 +14,18 @@ export default function hash(args: any[]): string { for (let i = 0; i < args.length; ++i) { let _hash if (typeof args[i] !== 'object') { - _hash = String(args[i]) + // need to consider the case that args[i] is a string: + // args[i] _hash + // "undefined" -> '"undefined"' + // undefined -> 'undefined' + // 123 -> '123' + // null -> 'null' + // "null" -> '"null"' + if (typeof args[i] === 'string') { + _hash = '"' + args[i] + '"' + } else { + _hash = String(args[i]) + } } else { if (!table.has(args[i])) { _hash = counter From f985370979332d3b1afdf1abecd29d936f1295c6 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 26 Nov 2019 15:36:46 +0800 Subject: [PATCH 3/6] add prefetch to the readme --- README.md | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ad7ea49d5..a610fa2ed 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ of `fetcher` and rerenders the component. Note that `fetcher` can be any asynchronous function, so you can use your favourite data-fetching library to handle that part. -Check out [swr.now.sh](https://swr.now.sh) for more demos of SWR. +Check out [swr.now.sh](https://swr.now.sh) for more demos of SWR, and [Examples](#examples) for the best practices.
@@ -137,10 +137,11 @@ You can also use [global configuration](#global-configuration) to provide defaul - [Dependent Fetching](#dependent-fetching) - [Multiple Arguments](#multiple-arguments) - [Manually Revalidate](#manually-revalidate) -- [Local Mutation](#local-mutation) +- [Mutation and Post Request](#mutation-and-post-request) - [SSR with Next.js](#ssr-with-nextjs) - [Suspense Mode](#suspense-mode) - [Error Retries](#error-retries) +- [Prefetching Data](#prefetching-data) ### Global Configuration @@ -309,7 +310,7 @@ function App () { } ``` -### Local Mutation +### Mutation and Post Request In many cases, applying local mutations to data is a good way to make changes feel faster — no need to wait for the remote source of data. @@ -418,6 +419,29 @@ useSWR(key, fetcher, { }) ``` +### Prefetching Data + +There’re many ways to prefetch the data for SWR. For top level requests, [`rel="preload"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content) is highly recommended: + +```html + +``` + +This will prefetch the data before the JavaScript starts downloading. And your incoming fetch requests will reuse the result (including SWR, of course). + +Another choice is to prefetch the data conditionally. You can have a function to refetch and set the cache: + +```js +function prefetch () { + mutate('/api/data', fetch('/api/data').then(res => res.json())) + // the second parameter is a Promise + // SWR will use the result when it resolves +} +``` + +And use it when you need to preload the **resources** (for example when [hovering](https://github.com/GoogleChromeLabs/quicklink) [a](https://github.com/guess-js/guess) [link](https://instant.page)). +Together with techniques like [page prefetching](https://nextjs.org/docs#prefetching-pages) in Next.js, you can load both the next page and data almost instantly. +
## Authors From f9a25957d27016613678ad2bba11d4e3648df1e0 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 26 Nov 2019 15:37:51 +0800 Subject: [PATCH 4/6] improve wording --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a610fa2ed..c8570fc9f 100644 --- a/README.md +++ b/README.md @@ -440,7 +440,7 @@ function prefetch () { ``` And use it when you need to preload the **resources** (for example when [hovering](https://github.com/GoogleChromeLabs/quicklink) [a](https://github.com/guess-js/guess) [link](https://instant.page)). -Together with techniques like [page prefetching](https://nextjs.org/docs#prefetching-pages) in Next.js, you can load both the next page and data almost instantly. +Together with techniques like [page prefetching](https://nextjs.org/docs#prefetching-pages) in Next.js, you will be able to load both next page and data instantly.
From cbb3cc989ede918502fe30bf457a0764fe5e24f7 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 26 Nov 2019 15:47:58 +0800 Subject: [PATCH 5/6] return cached state and remove hydration, fixes #144 --- src/use-swr.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/use-swr.ts b/src/use-swr.ts index d9cd83306..5d09d2baa 100644 --- a/src/use-swr.ts +++ b/src/use-swr.ts @@ -543,8 +543,8 @@ function useSWR( error: state.error, // `key` might be changed in the upcoming hook re-render, // but the previous state will stay - // so we need to match the latest key and data - data: keyRef.current === key ? state.data : undefined, + // so we need to match the latest key and data (fallback to `initialData`) + data: keyRef.current === key ? state.data : initialData, revalidate, // handler isValidating: state.isValidating } From 27ae34eec150dd438a4cd9cd1c017e723d6f750f Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 26 Nov 2019 15:53:23 +0800 Subject: [PATCH 6/6] remove useHydration --- src/use-swr.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/use-swr.ts b/src/use-swr.ts index 5d09d2baa..c8a307607 100644 --- a/src/use-swr.ts +++ b/src/use-swr.ts @@ -33,7 +33,6 @@ import defaultConfig, { } from './config' import SWRConfigContext from './swr-config-context' import isDocumentVisible from './libs/is-document-visible' -import useHydration from './libs/use-hydration' import throttle from './libs/throttle' import hash from './libs/hash' @@ -186,12 +185,8 @@ function useSWR( fn = config.fetcher } - // it is fine to call `useHydration` conditionally here - // because `config.suspense` should never change - const shouldReadCache = config.suspense || !useHydration() - const initialData = - (shouldReadCache ? cacheGet(key) : undefined) || config.initialData - const initialError = shouldReadCache ? cacheGet(keyErr) : undefined + const initialData = cacheGet(key) || config.initialData + const initialError = cacheGet(keyErr) let [state, dispatch] = useReducer>(mergeState, { data: initialData, @@ -540,10 +535,10 @@ function useSWR( } return { - error: state.error, // `key` might be changed in the upcoming hook re-render, // but the previous state will stay // so we need to match the latest key and data (fallback to `initialData`) + error: keyRef.current === key ? state.error : initialError, data: keyRef.current === key ? state.data : initialData, revalidate, // handler isValidating: state.isValidating