I am trying to use unstable_cache
on a server component to cache data in order to improve performance. However, it doesn’t seem working.
Below is my code. The fetchProductWithCache
is called from react component render function every time when a request comes. The revalidate time is 10 seconds. I assume all requests within 10 seconds shouldn’t call fetchProductWithDelay
from fetchProductWithCache
method. However, I can see every request has 1 second latency and the log fetch product from unstable_cache
is printed on every request. So it seems the unstable_cache
doesn’t really cache anything.
What am I doing wrong?
export const runtime = 'edge'; // I want to deploy to all edge locations
export const revalidate = 10;
const fetchProductWithCache = async (country?: Country) => {
const product = await unstable_cache(
async () => {
console.log('fetch product from unstable_cache');
return fetchProductWithDelay(country);
},
['product'],
{ revalidate: 10, tags: ['product'] }
)();
return product;
};
export const generateStaticParams = async () => {
const countries = await api.product.countries();
console.log('[PRODUCT] generating static paths:', countries);
return countries.map((country) => ({ country }));
};
export default async function Page({ params }: { params: Props }) {
const { country } = params;
console.log('[PRODUCT] generating static product:', country);
const product: any = await fetchProductWithCache(country)
const parityPrice = getDiscountedPrice(product.price, product.discount);
if (Object.keys(country).length === 0 || country === null || !product) {
return <div />;
}
return (
<>
<div className="ml-14 lg:ml-24 -mb-40 lg:-mb-56">
...
2
Answers
The unstable_cach should be used to wrap the whole function (fetchProductWithCache)
I cannot comment yet, but to clarify Josh Fradley’s answer:
The problem with your code is that it is calling
unstable_cache()
every time you callfetchProductWithCache
. The code is creating a new instance of the cached function for each call tofetchProductWithCache
, effectively creating a new independent cache entry but for the same key. This is very prone to race conditions in regards to the cached data returned. It is just plain incorrect.The correct way is to do what Josh Fradley wrote. Declare your cached function once, meaning only call
unstable_cache()
once for the function you want to cache. Then call that function with your argument for country.So replace your declaration of
fetchProductWithCache
with his and it should work.BTW, just a heads up. You cannot mix time based revalidation with tags.