Next 14 Caching my own api requests
Unanswered
Gray Flycatcher posted this in #help-forum
Gray FlycatcherOP
Hi, I am trying to cache my api request located at /api/admin/getProducts, so that any time people request it it gives the cache, but when its tag is revalidated (when a product stock is updated) it revalidates it and runs the code within that api request again so that the returning response is the updated getProducts, I have tried this with revalidateTag and the tag stuff but it just isnt working.
38 Replies
West African Lion
You can use this code.
https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate
export const revalidate = false
https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate
Gray FlycatcherOP
i used that as well
what does your code looks like?
Gray FlycatcherOP
ive got this admin page which gets the products, and displays them:
then the getProducts route is
async function fetchProducts() {
try {
const response = await (await fetch('/api/admin/getProducts', {next: { tags: ["testinggg"]}})).json();
setProducts(response);
setStartProducts(response);
} catch (error) {
console.error('Error fetching products:', error);
} finally {
setLoading(false);
}
}
fetchProducts();
}, []);
then the getProducts route is
import { NextResponse } from 'next/server';
import { GET as allProductSlugs } from '@/app/api/admin/getRecord/allProductSlugs/route';
import { GET as getProductById } from '@/app/api/admin/getRecord/[slug]/route';
import { GET as getPriceById } from '@/app/api/admin/getPrice/[priceId]/route';
export const revalidate = false;
export async function GET() {
try {
const allProductSlugsResponse = await allProductSlugs();
const slugs = await allProductSlugsResponse.json();
console.log("PRODUCTS")
const enrichedProducts = await Promise.all(
slugs.map(async (slug) => {
try {
const productResponse = await getProductById(undefined, { params: { slug } });
const product = await productResponse.json();
const priceResponse = await getPriceById(undefined, { params: { priceId: product.stripePriceId } });
const price = await priceResponse.json();
return {
...product,
price: price || null,
};
} catch (error) {
console.error(`Failed to fetch data for slug ${slug}:`, error.message);
return null;
}
})
);
const validProducts = enrichedProducts.filter((product) => product !== null);
return NextResponse.json(validProducts);
} catch (error) {
console.error('Error fetching all products:', error.message);
return NextResponse.json({ error: 'Failed to fetch products.' }, { status: 500 });
}
}
then in the update products api request, it does this revalidateTag('testinggg');
, but nothing is revalidating.Where is this code being used?
Gray FlycatcherOP
i’m calling the api request inside the code for a page, in a use effect
those tags wont work in client-side fetches
you have to put it in the server
Gray FlycatcherOP
ohh right so do I have to put it in a server side prop or smth
Gray FlycatcherOP
yeah in the next response
no not in the next response
Gray FlycatcherOP
i thought you can do like NextResponse.json(thing, {next:{tags:[…]}})
also wdym by here
Like in here, you dont need to put tags since you can just use revalidatePath(getProductRoute)
Gray FlycatcherOP
oh i see, as next js caches every api route in next14
i’ll try that
well not every api, but you can try adding these
export const dynamic = 'force-static'
nextjs allows you to set the cache for every route in nextjs.
Gray FlycatcherOP
and will that still allow recalibrate path to revalidate
even tho it’s static
yeah
make sure you aren't using dynamic functions
otherwise you need to set the route as
dynamic
and cache the functions not the routeGray FlycatcherOP
wdym by dynamic functions
Gray FlycatcherOP
@Alfonsus Ardani woukd it work by doing this, and putting the tag inside the api route, any requests to that api route use the cache?
you can't put the tags in NextResponse if i remember correctly.
Gray FlycatcherOP
if i use revalidate path and leave the rest as normal, provided fetch requests are done server side, should that work so that every request to that api is cached until revalidated?
if fetch are done server side, and you are hitting your own api, its better to import the function directly rather than making a server request to the same server you are already in.
Gray FlycatcherOP
also what do i do instead of getServerSideProps using the app router, rather than pages?
Just write the data fetching methods directly in page.js or layout.js
Gray FlycatcherOP
okay so I now have this:
then in another route im doing
import { GET as getProducts } from '@/app/api/admin/getProducts/route';
import { GET as getBoxes } from '@/app/api/admin/getBoxes/route';
import AdminClientBit from "@/app/components/adminClientBit";
export default async function AdminPage() {
const {products, boxes} = (await getStuff()).props
return (
<AdminClientBit productss={products} boxess={boxes} />
)
}
async function getStuff() {
try {
const products = await (await getProducts()).json();
const boxes = await(await getBoxes()).json();
return {
props: {
products,
boxes
},
};
} catch (error) {
return {
props: {
products: [],
boxes: []
},
};
}
}
/src/app/api/admin/getProducts/route.js
import { NextResponse } from 'next/server';
export const revalidate = false;
export const dynamic = 'force-static'
export async function GET() {
try {
//...
return NextResponse.json(validProducts);
} catch (error) {
//...
return NextResponse.json({ error: 'Failed to fetch products.' }, { status: 500 });
}
}
then in another route im doing
revalidatePath('/api/admin/getProducts');
and its still not revalidating the cachewhere did you put
revalidatePath
?