在 React/Next.js 中,cache
是 React 18+ 提供的一个实验性 API,用于 跨组件渲染周期缓存数据,避免重复计算或请求。
1. cache
的核心作用
- 缓存函数结果:相同输入下直接返回缓存值,跳过重复执行。
- 跨组件共享缓存:多个组件调用同一函数时复用缓存。
- 自动垃圾回收:缓存会随组件卸载自动清理。
2. 基本用法
(1) 缓存普通函数
import { cache } from "react";
// 定义缓存函数
const getData = cache(async (id) => {
const res = await fetch(`https://api.example.com/data/${id}`);
return res.json();
});
// 组件中使用
async function ComponentA({ id }) {
const data = await getData(id); // 首次调用会请求,后续复用缓存
}
async function ComponentB({ id }) {
const data = await getData(id); // 直接读取缓存
}
(2) 缓存 React 组件
const CachedComponent = cache(function MyComponent({ data }) {
return <div>{data}</div>;
});
function Parent() {
return (
<>
<CachedComponent data="A" /> {/* 首次渲染 */}
<CachedComponent data="A" /> {/* 跳过渲染,复用缓存 */}
</>
);
}
3. Next.js 中的关键应用场景
(1) 数据请求去重
// utils/fetch.js
export const fetchUser = cache(async (id) => {
const res = await fetch(`/api/users/${id}`);
return res.json();
});
// 多个地方使用同一数据
async function Profile() {
const user = await fetchUser(1); // 实际只发一次请求
}
async function Dashboard() {
const sameUser = await fetchUser(1); // 读取缓存
}
(2) 优化服务端组件
// app/page.js
import { cache } from "react";
import db from "lib/db";
const getPosts = cache(() => db.posts.findMany());
export default async function Page() {
const posts = await getPosts(); // 同请求只执行一次
return <PostList posts={posts} />;
}
4. 缓存行为控制
(1) 手动清除缓存
import { unstable_cache } from "next/cache";
const getData = unstable_cache(
async () => fetchData(),
["data-key"], // 缓存键
{ revalidate: 3600 } // 1小时后失效
);
(2) 动态缓存键
const getUser = cache(async (id, role) => {
// 根据参数自动生成缓存键
});
const user1 = await getUser(1, "admin"); // 独立缓存
const user2 = await getUser(1, "user"); // 不同缓存
5. 与 Next.js 缓存机制对比
| 特性 | react/cache
| Next.js unstable_cache
|
| -------------- | -------------------- | ------------------------ |
| 作用范围 | 单次渲染周期 | 跨请求持久化 |
| 适用场景 | 组件间共享数据 | 全应用级数据缓存 |
| 失效控制 | 组件卸载自动清理 | 需手动设置 revalidate
|
| 数据新鲜度 | 每次渲染可能重新执行 | 可配置过期时间 |
6. 性能优化示例
缓存昂贵计算
const calculateStats = cache((data) => {
// 假设是复杂计算
return expensiveCalculation(data);
});
function Chart({ data }) {
const stats = calculateStats(data); // 相同data跳过计算
return <svg>{/* ... */}</svg>;
}
避免重复 API 调用
// 多个组件需要相同数据
const fetchGlobalConfig = cache(async () => {
return fetch("/api/config");
});
async function Header() {
const config = await fetchGlobalConfig();
}
async function Footer() {
const sameConfig = await fetchGlobalConfig(); // 命中缓存
}
7. 注意事项
- 仅服务端使用:
cache
主要针对 Server Components,客户端组件需用useMemo
。 - 不可变参数:缓存依赖参数需可序列化(如字符串/数字,避免对象/函数)。
- 调试技巧:
console.log(cache); // 查看缓存实例(开发环境)
总结
- 何时用:跨组件共享数据、避免重复计算/请求时。
- 最佳实践:
- 对纯函数或数据获取函数使用
cache
- 结合 Next.js 的
unstable_cache
实现长期缓存 - 避免缓存高频变化的动态数据
- 对纯函数或数据获取函数使用
通过合理使用 cache
,可显著提升 React/Next.js 应用的渲染效率! 🚀