Next 13中如何实现API获取的全局分类常量复用?
可行实现方案及替代思路
方案1:构建时预生成静态常量文件(推荐,无环境差异)
如果分类数据不会频繁更新,直接在构建阶段拉取API数据生成静态常量文件,后续所有代码直接导入使用即可,彻底避免服务端/客户端环境差异问题。
- 编写Node脚本拉取分类数据并生成常量文件:
// scripts/fetch-categories.js const fs = require('fs'); const fetch = require('node-fetch'); async function generateCategoryConstants() { // 调用外部API获取分类数据 const res = await fetch('https://your-api-domain/categories'); const categories = await res.json(); // 转成可直接导入的JS常量格式 const constantContent = `export const CATEGORIES = ${JSON.stringify(categories, null, 2)};`; // 写入项目目录,比如utils文件夹下 fs.writeFileSync('./app/utils/category-constants.js', constantContent); } generateCategoryConstants();
- 在
package.json的构建脚本前添加预执行命令,确保每次构建前自动拉取最新分类:
{ "scripts": { "prebuild": "node scripts/fetch-categories.js", "build": "next build", // 其他脚本... } }
- 全局复用:在普通JS文件、SSR/客户端组件里直接导入即可:
import { CATEGORIES } from '@/app/utils/category-constants'; // 示例判断逻辑 if (product.categoryId === CATEGORIES.DRINKS.id) { // 处理饮品分类产品 }
方案2:运行时全局缓存+Context传递(适合动态更新场景)
如果分类数据需要在运行时动态获取(比如构建后可能更新),通过全局缓存确保仅请求一次,再结合React Context让客户端组件便捷访问。
- 创建全局缓存模块:
// app/utils/category-cache.js let cachedCategories = null; export async function getCategories() { // 缓存存在则直接返回,避免重复请求 if (cachedCategories) return cachedCategories; const res = await fetch('https://your-api-domain/categories', { // 开启Next.js缓存,服务端客户端共享缓存 cache: 'force-cache' }); cachedCategories = await res.json(); return cachedCategories; }
- 根布局(Server Component)预取数据并注入Context:
// app/layout.js import { createContext, useContext } from 'react'; import { getCategories } from '@/app/utils/category-cache'; const CategoriesContext = createContext(null); export async function RootLayout({ children }) { // 服务端预取分类数据,仅执行一次 const categories = await getCategories(); return ( <html lang="zh-CN"> <body> <CategoriesContext.Provider value={categories}> {children} </CategoriesContext.Provider> </body> </html> ); } // 封装自定义Hook供客户端组件使用 export function useCategories() { const context = useContext(CategoriesContext); if (!context) throw new Error('useCategories必须在CategoriesContext.Provider范围内使用'); return context; }
- 全局复用方式:
- 服务端组件/普通JS文件:直接调用
getCategories()(缓存自动生效) - 客户端组件:使用
useCategories()Hook获取数据
方案3:结合RTK Query缓存(适配已有RTK的项目)
如果项目已经使用Redux Toolkit,直接利用RTK Query的缓存机制管理分类数据,确保全局仅请求一次。
- 创建分类API切片:
// app/store/api/categoriesApi.js import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; export const categoriesApi = createApi({ reducerPath: 'categoriesApi', baseQuery: fetchBaseQuery({ baseUrl: 'https://your-api-domain/' }), endpoints: (builder) => ({ getCategories: builder.query({ query: () => 'categories', // 设置永久缓存,避免重复请求 keepUnusedDataFor: Infinity }) }) }); // 客户端组件用Hook export const { useGetCategoriesQuery } = categoriesApi; // 非组件环境(普通JS/服务端)获取缓存数据的方法 export async function getCategoriesFromCache(store) { const state = store.getState(); const cachedData = categoriesApi.endpoints.getCategories.select()(state); if (cachedData.data) return cachedData.data; // 缓存不存在则发起请求并等待结果 const result = await store.dispatch(categoriesApi.endpoints.getCategories.initiate()); return result.data; }
- 全局复用方式:
- 客户端组件:使用
useGetCategoriesQuery()获取数据 - 服务端组件/普通JS文件:通过Redux Store调用
getCategoriesFromCache()获取缓存数据
内容的提问来源于stack exchange,提问作者user24751344
相关产品推荐
相关产品推荐

