React's cache()
memoizes your function calls when rendering server components.
This short-lived cache is useful when you are fetching data in multiple places, for example a layout and a page that both fetch the current user.
One of the problems with co-locating data fetching and rendering in async components is that these components are now blocked while they’re fetching data.
For example, all your components that fetch the current user are now on the hook for that network latency.
In client React we have context and module-scoped external stores to manage loading states and shared fetches, but in RSC we don’t have access to those tools.
- No context because no re-renders
- No external stores because module scope is shared by multiple requests
This is where cache
comes in: it gives us a place to stash data, on a per request basis, while rendering RSCs:
import { cache } from "react";
export default async function Page() {
let article = await getTopArticle();
return (
<div>
The top article is {article.title}
<Again />
<Again />
<Again />
</div>
);
}
async function Again() {
let article = await getTopArticle();
return <div>Again, it's {article.title}</div>;
}
// This function is called in four places,
// but it will only run once!
let getTopArticle = cache(async () => {
return db.query("select * from articles...");
});
In this example, after one component fetches the top article, all other components that need the article will re-use the result of the first fetch. React only makes one database query even though multiple components are calling getTopArticle()
.