我有一个简单的nextjs 13
应用程序(appDir),有两个页面和一个<Link/>
组件导航。
- 首页
Home
- static - 第二页
Test
-从第三方源接收服务器端动态随机内容。
问题:当应用程序呈现一切工作正常,但当我试图在页面之间切换,我的测试页面显示旧的内容,我可以刷新浏览器来获得实际数据,是非常类似于导航通过常规链接<a/>
,但我需要不重新加载整个应用程序。
Q:当我在<Link/>
组件的页面之间切换时,我如何强制nextjs 13
重新加载Test
页面?
// src/components/navbar.tsx
'use client'
import {usePathname} from "next/navigation";
import Link from "next/link";
const navItems = [
{text: 'Home', href: '/'},
{text: 'Test', href: '/test'}
];
const Navbar = () => {
const pathname = usePathname();
return <nav className="nav nav-masthead justify-content-center float-md-end">
{navItems.map((item: { text: string, href: string, link?: boolean }, idx: number) => (
<Link key={idx} href={item.href} className={`nav-link${item.href === pathname ? ' active' : ''}`}>
{item.text}
</Link>
)
)}
</nav>
}
export default Navbar;
// src/app/test/page.tsx
import * as crypto from "crypto";
const getData = async () => {
const res = await fetch('http://localhost:3000/random-data', {cache: 'no-store'});
if (!res.ok) {
throw new Error('Failed to fetch data');
}
return res.json();
}
export default async function Page() {
return <p>{crypto.createHash('sha256').update(JSON.stringify(await getData())).digest('hex')}</p>
};
我最近在github上的反馈讨论中询问了相同的主题:https://github.com/vercel/next.js/discussions/41745?sort=new#discussioncomment-4620262
问题的原因是Link
只做客户端导航,似乎服务于以前访问的组件的缓存状态。您将注意到客户端永远不会回调服务器,因此服务器组件永远不会运行第二次。
我已经搜索了几天,但还没有找到一种方法来强制Link
重新加载或强制刷新组件重新渲染。
我的结论是,如果你有需要定期刷新的动态数据,最好在客户端组件中呈现它,而不是现在使用服务器组件。
另外,如果你想使用悬念,你需要使用像SWR或React Query这样的库来获取任何客户端数据。
一个似乎有效的解决方案是在SSR布局模板页面上包含一个客户端组件,在挂载时强制刷新。
起初,它似乎会导致无限刷新循环,但测试结果很好。唯一的问题是页面导航的额外刷新。
// Sample Refresher Component
// to be imported into SSR page
// needing a refresh after
// next.js appDir Link nav
//
// tested in next.js 13.2.3
'use client'
import { useRouter } from 'next/navigation'
import { useEffect } from 'react'
export function Refresher() {
const router = useRouter()
useEffect(() => {
router.refresh()
}, [router])
return <></>
}
我认为尝试更新一个组件(或多个组件)而不是整个页面是有益的。
所以,让Test
页面呈现多个组件,一些服务器(可以只是静态内容)和一些动态使用客户端。现在应该是这样,client
组件可以在自己内部使用client hooks
,只在需要时更新/重新渲染自己。
简单地,把你的page
分解成组件。