Question about Data Caching
Answered
Little fire ant posted this in #help-forum
Little fire antOP
Hello, I'm a Next.js newbie and I'm pretty sure what I'm stuck on is pretty much easy to solve but for the life of me I cannot find a fix or even what exactly is the problem. I believe it has something to do with optimization and caching of data.
I have a component that fetches an API route that returns some data. I'm using SWR for the fetch, as when I started having this problem, I was using the fetch API itself, and digging through the docs, I read that using SWR might help, but so far I had no luck.
# What's the problem?
I believe that the data is being fetched once, upon building the project. It is then cached, and never revalidated, so whenever the data is mutated, optimistic data kicks in, shows correct data, and then refetch kicks in and overwrites it with old data.
# What have you done to fix it?
I tried the following snippets to my code
## The fetcher
This may look overkill, but I had tried each option beforehand,
## The SWR instance.
## One of the data handlers, showing the Mutate func.
I have a component that fetches an API route that returns some data. I'm using SWR for the fetch, as when I started having this problem, I was using the fetch API itself, and digging through the docs, I read that using SWR might help, but so far I had no luck.
# What's the problem?
I believe that the data is being fetched once, upon building the project. It is then cached, and never revalidated, so whenever the data is mutated, optimistic data kicks in, shows correct data, and then refetch kicks in and overwrites it with old data.
# What have you done to fix it?
I tried the following snippets to my code
## The fetcher
const fetcher = (url: string) =>
fetch(url, { cache: 'no-store', next: { revalidate: 0 } }).then((res) => res.json());This may look overkill, but I had tried each option beforehand,
cache: 'no-store' and next: {revalidate: 0}, neither had worked.## The SWR instance.
const {
data: users,
error: usersError,
isLoading: userLoading,
isValidating: userValidating,
mutate: userMutate,
} = useSWR('/api/users', fetcher, {
refreshInterval: 1000,
});## One of the data handlers, showing the Mutate func.
function handleDelete(id: number) {
const optimisticData = users.filter((user: User) => user.id !== id);
userMutate(optimisticData, false);
}19 Replies
Little fire antOP
I feel really bad writing this because I feel like it's something so easy, simple and stupid that I'm just missing out on, but I also believe that if I'm having trouble with this, someone else may as well.
I also have the impression Next.js is fighting against me, and so that this may not be good practice. While I do get it, that refetching the database every few seconds is subpar, I would also like the shown data to be somewhat updated, not necessarily in real time. What is happening here? Is Next.js fetching the data once on building and feeding that same, somewhat immutable data to clients? If this behaviour makes it so that every once in a while one connection is made to the DB to fetch data and this data is then fed to everyone who needs it, how can I then keep this behaviour happening but revalidate said data every x amount of time?
I also have the impression Next.js is fighting against me, and so that this may not be good practice. While I do get it, that refetching the database every few seconds is subpar, I would also like the shown data to be somewhat updated, not necessarily in real time. What is happening here? Is Next.js fetching the data once on building and feeding that same, somewhat immutable data to clients? If this behaviour makes it so that every once in a while one connection is made to the DB to fetch data and this data is then fed to everyone who needs it, how can I then keep this behaviour happening but revalidate said data every x amount of time?
Milkfish
Where's the data being fetched from?
Little fire antOP
It's being fetched from a MySQL DB, hosted in a company server.
Milkfish
Are you fetching the data in a route handler, and then the client fetches the route handler? Or are you fetching the data from the company server directly on the client?
Little fire antOP
Yes, I am fetching data through an API route handler. It fetches /api/users, which has a route.ts
The route.ts in question:
import { NextRequest, NextResponse } from 'next/server';
import prisma from '@/lib/prisma';
export async function GET(req: NextRequest, res: NextResponse) {
const users = await prisma.funcionarios.findMany({});
console.log('Fetch for users made.');
return NextResponse.json(users);
}This has been working, so far, although today I sat down at the computer to try and fix this again and now I'm getting another error, which I believe is unrelated. I'm attempting to fix it, so I can build the project and see if any solutions work.
Milkfish
Route handlers using GET handlers are cached by default
Answer
Milkfish
add the following to your page file
export const dynamic = 'force-dynamic'
Little fire antOP
Is that forcing a setting in Next?
Milkfish
Yes, forcing the route handler to be dynamic instead of generating a static page at build time
Little fire antOP
Ah, I see. Can I put it inside the API route? So it's somewhat uniform across the entire project?
Milkfish
you'll need to put it in any page that you want to be dynamic, e.g. your route.ts file
Little fire antOP
Alright, I'll get to it. Thank you, Mike, as soon as I'm able to test this, I'll report back.
Little fire antOP
Building at the company's computer is simply not working. I'll dig into this deeper, but for now, building at Vercel has worked, and so far, desired behaviour is being observed. DB mutations are being reflected nicely. Thank you!
I would still like to ask, is this "best-practice"? Because the DB is going to be accessed more often, right?
@Milkfish Thank you so much, you're a life-saver. Been stuck on this for some time now.