I am using SWR to fetch data to populate a table with. I am using the following code:
const { data: items, error } = useSWR(fetchAllItems.name, fetchAllItems)
The fetcher function looks like this
async function fetchAllItems() {
const response = await fetch('http://localhost:3000/items')
const data = await response.json()
return data
}
The table also has an options to add a new item. After creating the new item I call mutate to let SWR fetch the new data. While running this in development mode it all works great, however when using next start instead of next dev it won't fetch the data. In the networks tab it shows 0 requests, so it looks like the fetcher function is never called.
The server where the data is fetched from is running properly. I have tested this using postman and it returns all the items. It is also accessible from the next application, because creating a new item works fine.
EDIT: After some more debugging I have narrowed it down to the fact that SWR is never validating when using next start instead of next dev.
EDIT 2: A codesandbox with a minimal reproducible example can be found here https://codesandbox.io/s/elated-cherry-3ugqyi?file=/package.json . De codesandbox runs the program using npm run dev
(which calls next dev) so everything works fine. However when running it with npm run build && npm run start
useSWR no longer calls the fetcher function.
EDIT 3: I have resolved the issue, but don't understand how. I changed the fetcher function to the following:
function fetchAllItems() {
return fetch('http://localhost:3000/items').then((res) => res.json())
}
The fetcher function is now no longer async, however it still returns a Promise (because fetch returns a Promise). If anyone could explain why this code behaves differently from the previous that would be great.
Your fetcher function is fine as is. The issue occurs because in the production build fetchAllItems.name
resolves to an empty string ''
, meaning useSWR
will not call the fetcher function as the key
param is a falsy value.
You have two options to solve the problem.
useSWR
keySimply use a string as the key
parameter in the useSWR
. I'd recommend this approach, as using fetchAllItems.name
may not always return the expected value in production.
const { data: items, error } = useSWR('fetchAllItems', fetchAllItems)
fetchAllItems
Use the named function format for the fetchAllItems
function, instead of an arrow function. This was probably what fixed the issue for you when you defined the new function without async
/await
.
export async function fetchAllItems() {
const response = await fetch('http://localhost:3000/items')
const data = await response.json()
return data
}