使用router.refresh()时Suspense fallback未显示的问题
问题解决:点击刷新按钮时显示Suspense的fallback内容
问题原因
router.refresh() 触发页面服务器组件重新渲染时,Next.js 默认不会触发客户端的 Suspense fallback 展示——这个 fallback 主要在初始服务端渲染或客户端路由跳转时生效,页面内的刷新操作不会主动触发加载状态的显示。
解决方案:手动管理加载状态
我们可以通过客户端状态控制加载状态,在点击刷新按钮时显示骨架屏,直到刷新完成后隐藏。
方案1:基础状态控制
步骤1:修改 Home 页面为客户端组件,添加加载状态
'use client' import { useState } from 'react' import RefreshBtn from './RefreshBtn' import NoteSkeleton from './NoteSkeleton' import Feed from './Feed' const Home = () => { const [isRefreshing, setIsRefreshing] = useState(false) return ( <> <RefreshBtn onStartRefresh={() => setIsRefreshing(true)} onFinishRefresh={() => setIsRefreshing(false)} /> {isRefreshing ? <NoteSkeleton /> : <Feed />} </> ) } export default Home
步骤2:修改 RefreshBtn 组件,传递状态回调
'use client' import { useRouter } from 'next/navigation' function RefreshBtn ({ onStartRefresh, onFinishRefresh }) { const router = useRouter(); const handleBtn = async () => { onStartRefresh() await router.refresh() // 因router.refresh()无返回值,可根据接口响应速度调整延迟时间 setTimeout(() => onFinishRefresh(), 300) } return ( <button onClick={handleBtn}>Refresh</button> ); }; export default RefreshBtn;
方案2:结合 React 过渡 API 保留 Suspense 写法
'use client' import { useState, useTransition } from 'react' import RefreshBtn from './RefreshBtn' import NoteSkeleton from './NoteSkeleton' import Feed from './Feed' const Home = () => { const [isPending, startTransition] = useTransition() const [refreshKey, setRefreshKey] = useState(0) const handleRefresh = () => { startTransition(() => { setRefreshKey(prev => prev + 1) }) } return ( <> <RefreshBtn onRefresh={handleRefresh} /> <Suspense fallback={<NoteSkeleton />}> {/* 通过key变化强制Feed重新渲染,触发Suspense fallback */} <Feed key={refreshKey} /> </Suspense> </> ) } export default Home
同步修改 RefreshBtn:
'use client' function RefreshBtn ({ onRefresh }) { return ( <button onClick={onRefresh}>Refresh</button> ); }; export default RefreshBtn;
内容的提问来源于stack exchange,提问作者Elher Encarnacion
相关产品推荐
相关产品推荐

