我在 NextJs 中经常使用的一种模式是渲染服务器端的所有内容(包括数据获取),然后过渡到动态客户端渲染。人为的例子:
export async function getServerSideProps() {
const res = await fetch(`api/myData`)
const data = await res.json()
return {
props: { initialData: [data] }
}
}
export default function About({ initialData }) {
const [data, setData] = useState(initialData)
const addItem = () => {
const item = "foo"
const res = await fetch('/api/addData')
setData([...data, JSON.parse(res.body).item])
}
return (
<div>
{data.map(item => (<div>{item}</div>))}
<button onClick={addItem}>Add Item</button>
</div>
)
}
Run Code Online (Sandbox Code Playgroud)
我不知道如何通过构建 NextJs 的新 App Router 风格获得相同类型的功能。谁能告诉我我缺少什么?
让我们分步骤来分解:
您想要initalData动态获取服务器端,这意味着您需要在服务器组件中获取数据,我认为该page.tsx组件是实现此目的的一个很好的地方,因此示例页面组件是:
export default async function Page() {
const res = await fetch(`api/myData`, {cache: 'no-store'});
const data = await res.json();
return <About initialData={[data]} />
}
Run Code Online (Sandbox Code Playgroud)
请注意,fetch有cache: 'no-store',这是选择动态渲染所必需的,因为静态渲染是默认的,这也可以通过 来实现revalidate: 0。
您需要制作<About />一个客户端组件才能使用useState等。因此您需要'use client'在 About 组件文件的顶部添加。
要记住的一件事是,在现实世界的应用程序中,您可能希望静态渲染页面,解决方案是将我们所做的封装到单独的服务器组件中,并让该服务器组件获取数据并动态渲染,而不是整个页面组件。
还涉及客户端和服务器组件之间的动态。客户端组件实际上是在服务器中预渲染的(html/css 和一个小的 js 包),但它们也需要一个无法在服务器中运行的 js 负载,如果你仔细想想,在useState服务器中运行是没有意义的,因为状态存在于用户浏览器中,更不用说onClick在服务器中拥有侦听器了。当 nextjs 预渲染客户端组件时,它会发回渲染的 html/css/server js 以及需要在客户端中执行的客户端 js 有效负载。另一方面,服务器组件不需要客户端 js,因此服务器只返回 html/css 和一小段 js。在您的原始示例中,该组件getServerSideProps在服务器中执行,但该组件具有客户端负载,就像具有新应用程序文件夹路由器的<About />组件一样。当前不支持具有客户端代码(如并在服务器中呈现 100% use client)的组件,并且这种组件的意义为零。关于 html 和 css,正如我之前所说,它最初也是在服务器中为客户端组件预渲染的。您可以在这里阅读更多相关信息https://nextjs.org/docs/getting-started/react-essentials#client-componentsuseStateonClick
| 归档时间: |
|
| 查看次数: |
1985 次 |
| 最近记录: |