I am having an issue with the data I am receiving from my express server in my nextjs app.
I am making a fetch request to the endpoint ‘/product/category/:category’.
If a make this request using postman I get a response like so:
"data": [
{
"_id": "65a71532c33cc42a6ab218dd",
"name": "yx1 wireless earphones",
"description": "description here",
"new": true,
"alt": "yx1 wireless earphones",
"categoryImg": {
"mobile": "url1",
"tablet": "url2",
"desktop": "url3"
}
}
]
This is in my fetchProductsByCategory func:
const res = await fetch(
`http://localhost:3001/product/category/${category}`
);
if (!res.ok) {
console.log(res);
throw new Error("Failed to fetch data");
}
const data = await res.json();
return data;
The value of ‘data’ for the exact same endpoint (in fetch function) looks like this:
"data": [
{
"_id": "65a71532c33cc42a6ab218dd",
"name": "yx1 wireless earphones",
"description": "description here",
"new": true,
"alt": "yx1 wireless earphones"
}
]
the categoryImg property is completely removed? Why is this happening?
I can fix the problem by:
import { unstable_noStore as noStore } from "next/cache";
And then calling noStore() at the top of the fetchProductsByCategory function. Why does this solve the issue?
I am trying to teach myself web development, this is my first time using nextJS. Sorry if it is a stupid question.
import { unstable_noStore as noStore } from "next/cache";
is the hint to understanding the behaviour you’re seeing.
In short, Next.js caches fetch
requests (GET
& POST
) and it’s down to you to invalidate that cache in some manner. Note: there are some subtle differences depending on where you’re making the fetch requests E.g. route handlers.
Here’s a somewhat contrived example, but hopefully explains the general notion in a succinct way.
Functions for making the requests.
function getCategoryCacheTag(category: string) {
return `product_category_${category}`;
}
function getCategory(category: string) {
const url = `http://localhost:3001/product/category/${category}`;
const request: RequestInit = {
method: "GET",
next: {
// You can do a combination here, don't need both.
tags: [getCategoryCacheTag(category)], // Apply a tag to the request so we can revalidate the cache on demand
revalidate: 3600 // Revalidate the cache for this request every 60 minutes
}
};
const response = await fetch(url, request);
return response;
}
function updateCategory(category: string, someData: any) {
const url = `http://localhost:3001/product/category/${category}`;
const request: RequestInit = {
method: "POST",
cache: "no-cache" // Never cache this POST request because we're updating the category
body: JSON.stringify(someData)
};
const response = await fetch(url, request);
return response;
}
Update the category and revalidate because we know the category’s data should have changed. You’d often call this in a Server Action.
const category = "categoryA";
const response = await updateCategory(category, { dataA: "lorem", dataB: "ipsum"}); // Update the category
if (response.ok) {
revalidateTag(getCategoryCacheTag(category)); // Revalidate (clear) the category cache using its tag
}
It’s a bit of a read, but I would highly recommend reading the documentation about Next.js’ caching.
https://nextjs.org/docs/app/building-your-application/caching#data-cache
Cheers for the replies.
It did have to do with the cache. For some reason I thought the cache would reset each time you start/stop the server in dev mode. Not the case apparently.
What was happening is that I changed the collection (in my db) a while ago so that it included the categoryImg field. nextjs had data cached for these requests from before I changed this field. So when I removed noStore() it was serving cached data. Adding that function forces it to fetch the request each time a user navigated to that page I believe, hence it was grabbing the most recent data?
Any way, I just deleted the .next file, restarted the server and it worked as expected.
Hi, Next.js does not change the data received from an endpoint. Could you add more details? Is back-end and front-end Next.js 14? Are you using App router? Filenames?