服务端组件间共享数据:避免重复调用getPosts优化咨询
可行,以下是几种实现方案
方案一:将posts作为props传递
把数据获取逻辑统一放在父组件,再将posts传递给不同的布局组件,这样只会调用一次getPosts()。
修改后的代码示例:
import { getPosts } from "../../sanity-utils" // 布局组件改为接收posts props function ServerLayout({ posts }) { return ( <div className=""> {posts.map((post) => ( <div key={post.id } className=""> <h1>{post.title}</h1> <img src={post.image} alt="image" className="w-1/3 "/> </div> ))} </div> ); } function CardLayout({ posts }) { return ( <div className=""> {posts.map((post) => ( <div key={post.id } className="flex"> <h1>{post.title}</h1> <img src={post.image} alt="image" className="w-1/3 "/> </div> ))} </div> ); } // 父组件统一获取数据并传递给子组件 export default async function Page() { const posts = await getPosts(); return ( <div> <ServerLayout posts={posts} /> <CardLayout posts={posts} /> </div> ); }
方案二:缓存getPosts()的结果
如果不想通过props传递数据,可以给getPosts()添加缓存逻辑,这样即使多次调用该方法,也只会实际发起一次请求。
修改sanity-utils中的getPosts:
// sanity-utils.js let cachedPosts = null; export async function getPosts() { // 如果已有缓存,直接返回 if (cachedPosts) { return cachedPosts; } // 原数据请求逻辑,这里假设是调用Sanity API const response = await fetch('你的Sanity API地址'); cachedPosts = await response.json(); return cachedPosts; }
之后不管Server或Card组件如何调用getPosts(),第一次请求后都会复用缓存数据,不会重复发起请求。
方案三:使用React Context(适合组件层级较深的场景)
如果组件层级复杂,props传递太繁琐,可以用Context来全局共享posts数据。
import { createContext, useContext } from 'react'; import { getPosts } from "../../sanity-utils" const PostsContext = createContext(null); // 提供数据的Provider组件 async function PostsProvider({ children }) { const posts = await getPosts(); return ( <PostsContext.Provider value={posts}> {children} </PostsContext.Provider> ); } // 自定义Hook用于获取Context中的posts function usePosts() { const posts = useContext(PostsContext); if (!posts) throw new Error('usePosts必须在PostsProvider组件内部使用'); return posts; } // 布局组件通过usePosts获取数据 function ServerLayout() { const posts = usePosts(); return ( <div className=""> {posts.map((post) => ( <div key={post.id } className=""> <h1>{post.title}</h1> <img src={post.image} alt="image" className="w-1/3 "/> </div> ))} </div> ); } function CardLayout() { const posts = usePosts(); return ( <div className=""> {posts.map((post) => ( <div key={post.id } className="flex"> <h1>{post.title}</h1> <img src={post.image} alt="image" className="w-1/3 "/> </div> ))} </div> ); } // 父组件用PostsProvider包裹所有需要用到数据的组件 export default async function Page() { return ( <PostsProvider> <ServerLayout /> <CardLayout /> </PostsProvider> ); }
内容的提问来源于stack exchange,提问作者rlima003
相关产品推荐
相关产品推荐

