如何在Next.js的pages目录中启用Suspense使用SWR Hook?
如何在首页组件中使用SWR的suspense选项并让React Suspense生效?
我在项目中尝试使用SWR Hook,启用suspense: true选项时,将其放在首页组件中无法让Suspense正常工作,只有放在子组件里才能生效。请问如何在首页组件中直接使用SWR Hook并让Suspense生效?
原代码示例:
/pages/home.js:
export default function Home() { return ( <div> <h1>Home page</h1> <Suspense fallback={<Loading />}> <Post /> </Suspense> </div> ) }
/components/Post.js:
const Post= () => { const { data, mutate } = useSWR('/api/posts', fetcher, { suspense: true }) return ( <> {data.map(postItem=> ( <p key={postItem.id}> {postItem.title} </p> ))} </> ) }
解决方案
核心是让启用了suspense的useSWR调用处于Suspense组件的子组件树范围内。如果要在首页组件里直接实现,只需把SWR的调用逻辑封装成Home组件的内部子组件即可:
修改后的/pages/home.js:
import { Suspense } from 'react' import useSWR from 'swr' export default function Home() { // 内部组件封装SWR调用逻辑 const PostList = () => { const { data } = useSWR('/api/posts', fetcher, { suspense: true }) return ( <> {data.map(postItem => ( <p key={postItem.id}>{postItem.title}</p> ))} </> ) } return ( <div> <h1>Home page</h1> <Suspense fallback={<Loading />}> <PostList /> {/* 内部组件作为Suspense的子元素 */} </Suspense> </div> ) }
原理
React Suspense的机制是捕获其子组件树中的异步资源暂停状态。如果在Suspense的同级或父级组件中直接调用触发暂停的useSWR(启用了suspense: true),Suspense无法捕获到这个暂停事件,自然不会显示fallback加载状态。
不管是抽成外部子组件还是内部组件,本质都是让useSWR的调用被包含在Suspense的子组件树里,这样Suspense才能正常拦截并处理加载状态。
内容的提问来源于stack exchange,提问作者Epple
相关产品推荐
相关产品推荐

