Home > Back-end >  Re-fetch with useSWR hook when React Router Param changed
Re-fetch with useSWR hook when React Router Param changed

Time:02-05

I've found many questions similar to this, but all of them use normal fetching which could be handled by an useEffect hook, but it's not possible with useSWR.

Heres the code:

// simplified Router component:
export default function Router(){
  <BrowserRouter>
      <Routes>
        <Route path="/" element={<Layout />}>
          <Route index element={<MainPage />} />
          <Route path="post/:id" element={<Post />} />
        </Route>
      </Routes>
    </BrowserRouter>
}

// Post.tsx
export default function Post(){
  const {id} = useParams()
  const i = parseInt(id)
  const fetcher = (url) => axios.get(url, {id: i}).then(res => res.data)
  const {data} = useSWR('http://localhost:80/post', fetcher)
  return <div>
           {/*display post content */}
         </div>
}

I tried redirecting/reloading with useNavigate() but it didn't work.

CodePudding user response:

You could revalidate (mutate) the call if the param changes inside useEffect.

const { data, mutate } = useSWR('http://localhost:80/post', fetcher);

useEffect(() => {
   mutate('http://localhost:80/post', fetcher);
}, [param]);

or use the param as a key:

const { data, mutate } = useSWR(['http://localhost:80/post', param], fetcher);

and slightly modify the fetcher function:

const fetcher = ([url]) => axios.get(url, {id: i}).then(res => res.data)

CodePudding user response:

The way to do this is to update the key that useSWR uses (the key is the first argument to useSWR) in which case it'll just refetch automatically whenever the id changes, with the correct loading/error/etc states

  const {id} = useParams()
  const {data} = useSWR(`http://localhost:80/post/?id=${parseInt(id)}`, (url) => axios.get(url).then(res => res.data))

Any dependency (like the id) that is used to make a request should be part of useSWR's key.

Highly recommend Understanding SWR

  • Related