Next.js 13导航路由刷新后状态保留问题求助
解决Next.js中router.refresh()后客户端组件状态无法重置的问题
方案1:利用router.refresh()的Promise返回值
router.refresh()本身会返回一个Promise,当刷新操作(包括服务端数据重新获取、客户端页面更新)完成后,Promise会resolve。你可以通过async/await在刷新完成后直接重置状态,这是最简洁的解决方案:
'use client' import { useState } from 'react' import { useRouter } from 'next/navigation' import Button from './Button' export default function Refresh() { const [refreshing, setRefreshing] = useState(false) const router = useRouter() const handleClick = async () => { setRefreshing(true) await router.refresh() // 等待刷新完成 setRefreshing(false) } return ( <Button onClick={handleClick}> <i className={`bi bi-arrow-repeat text-lg ${refreshing ? 'animate-spin' : ''}`}></i> Refresh </Button> ) }
方案2:通过服务端传递的唯一标识触发状态重置
如果你的服务端组件每次刷新都会生成一个唯一标识(比如数据的更新时间戳、数据内容的哈希值),可以将这个标识作为props传递给客户端组件,通过useEffect监听该props的变化来重置状态:
服务端组件代码:
// 服务端组件 import Refresh from './Refresh' import { fetchData } from '@/lib/data' export default async function ServerComponent() { const data = await fetchData() // 用数据的更新时间或哈希作为唯一标识 const dataUpdateId = data.updatedAt || Date.now() return ( <div> {/* 渲染数据 */} <Refresh dataUpdateId={dataUpdateId} /> </div> ) }
客户端组件代码:
'use client' import { useState, useEffect } from 'react' import { useRouter } from 'next/navigation' import Button from './Button' export default function Refresh({ dataUpdateId }: { dataUpdateId: number | string }) { const [refreshing, setRefreshing] = useState(false) const router = useRouter() // 当服务端传递的标识变化时,重置刷新状态 useEffect(() => { if (refreshing) { setRefreshing(false) } }, [dataUpdateId]) const handleClick = () => { setRefreshing(true) router.refresh() } return ( <Button onClick={handleClick}> <i className={`bi bi-arrow-repeat text-lg ${refreshing ? 'animate-spin' : ''}`}></i> Refresh </Button> ) }
为什么你的临时方案能生效?
你用数组作为props的原因是每次服务端渲染都会创建新的数组引用,导致useEffect的依赖变化,从而触发状态重置。但这种方式不够直观,上面的方案2用业务相关的唯一标识替代无意义的数组,代码可读性和维护性更好。
内容的提问来源于stack exchange,提问作者Doğukan Akkaya
相关产品推荐
相关产品推荐

