examples/swr-site/content/en/docs/understanding.mdx
import { Video } from '@app/_components/video' import { Callout } from 'nextra/components'
useSWR returns data, error, isLoading, and isValidating depending on
the state of the fetcher function. This diagrams describe how SWR returns
values in some scenarios.
This pattern is to fetch data and revalidate it later.
This pattern is to fetch data and change the key and revalidate it later.
This pattern is to fetch data and change the key and revalidate it later with
the keepPreviousData option.
This pattern is to fetch data and revalidate it later with fallback data.
This pattern is to fetch data and change the key and revalidate it later with fallback data.
This pattern is to fetch data and change the key and revalidate it later with
the keepPreviousData option and fallback data.
Comparing to the existing isValidating value, isLoading is a new property
that can help you for the more general loading cases for UX.
isValidating becomes true whenever there is an ongoing request whatever
the the data is loaded or notisLoading becomes true when there is an ongoing request and data is not
loaded yet.Simply saying you can use isValidating for indicating everytime there is an
ongoing revalidation, and isLoading for indicating that SWR is revalidating
but there is no data yet to display.
function Stock() {
const { data, isLoading, isValidating } = useSWR(STOCK_API, fetcher, {
refreshInterval: 3000
})
// If it's still loading the initial data, there is nothing to display.
// We return a skeleton here.
if (isLoading) return <div className="skeleton" />
// Otherwise, display the data and a spinner that indicates a background
// revalidation.
return (
<>
<div>${data}</div>
{isValidating ? <div className="spinner" /> : null}
</>
)
}
You can find the code example here
When doing data fetching based on continuous user actions, e.g. real-time search
when typing, keeping the previous fetched data can improve the UX a lot.
keepPreviousData is an option to enable that behavior. Here's a simple search
UI:
function Search() {
const [search, setSearch] = React.useState('');
const { data, isLoading } = useSWR(`/search?q=${search}`, fetcher, {
keepPreviousData: true
});
return (
<div>
<input
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search..."
/>
<div className={isLoading ? "loading" : ""}>
{data?.products.map(item => <Product key={item.id} name={item.name} />)
</div>
</div>
);
}
With keepPreviousData enabled, you will still get the previous data even if
you change the SWR key and the data for the new key starts loading again.
<Video src="https://user-images.githubusercontent.com/3676859/163695903-a3eb1259-180e-41e0-821e-21c320201194.mp4" caption="Keep previous search results when keepPreviousData has been enabled" ratio={640 / 730} />
You can find the full code for this example here: https://codesandbox.io/s/swr-keeppreviousdata-fsjz3m.
SWR only triggers re-rendering when the states used in the component have been
updated. If you only use data in the component, SWR ignores the updates of
other properties like isValidating, and isLoading. This reduces rendering
counts a lot. More information can be found
here.