28
loading...
This website collects cookies to deliver better user experience
useSWR
, a React hook that makes all the complicated stuff in client side data fetching (caching, revalidation, focus tracking etc.) easy as pie.// Import the hook
import useSWR from 'swr'
// Define a custom fetcher function
const fetcher = (url) => fetch(url).then((res) => res.json())
function Profile() {
// Use the hook to fetch your data
const { data, error } = useSWR('/api/user', fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
/api/user
. But when you try to pass a dynamic route parameter to your useSWR
hook, things can get a little bit tricky. I recently spent some time figuring out a solution for this, so I thought I should share my solution./pages/user/[id].js
, which should show a user profile based on the ID we pass as a route parameter.// Import the useRouter hook from Next.js
import { useRouter } from 'next/router'
function Profile() {
// Use the useRouter hook
const router = useRouter()
// Grab our ID parameter
const { id } = router.query
return <div>user id: {id}</div>
}
http://localhost:3000/user/42
i.e), you should see the ID on the rendered page (user id: 42
). Now, instead of just rendering that ID, let's fetch the user related to that ID from our API endpoint and render a profile page.useSWR
hook and voilá – a beautiful profile page. The code looked like that:import useSWR from 'swr'
import { useRouter } from 'next/router'
const fetcher = (url) => fetch(url).then((res) => res.json())
function Profile() {
const router = useRouter()
const { id } = router.query
const { data, error } = useSWR(`/api/user/${id}`, fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
undefined
. But why? The ID was clearly there, so what the heck happened here?Pages that are statically optimized by Automatic Static Optimization will be hydrated without their route parameters provided, i.e query
will be an empty object ({}
). After hydration, Next.js will trigger an update to your application to provide the route parameters in the query
object.
getServerSideProps
or getStaticProps
on that page, Next turned on Automatic Static Optimization for it – which means the dynamic parameters from router.query
are not available until the hydration process has finished. Before, query
is just an empty object – that's why the network tab said undefined
.useSWR
to wait until our dynamic route parameter is ready?import useSWR from 'swr'
import { useRouter } from 'next/router'
const fetcher = (url) => fetch(url).then((res) => res.json())
function Profile() {
const router = useRouter()
const { id } = router.query
// Use a ternary operator to only fetch the data when the ID isn't undefined
const { data, error } = useSWR(id ? `/api/user/${id}` : null, fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
Loading...
, and as soon as the hydration process has finished it fetches the user data and renders the profile.