我在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>
)
}
而且我不知道如何使用构建NextJ的新App Router风格来获得相同的功能。谁能告诉我我错过了什么?
1条答案
按热度按时间r55awzrz1#
让我们按步骤分解:
1.你想动态地获取
initalData
服务器端,这意味着你需要在服务器组件中获取你的数据,我认为page.tsx
组件是一个很好的地方来实现这一点,所以一个示例页面组件是:注意,
fetch
有cache: 'no-store'
,这是为了选择进入动态渲染所需要的,因为静态渲染是默认的,这也可以用revalidate: 0
来实现。1.您需要使
<About />
成为客户端组件,以便能够使用useState
等。因此,您需要在About组件文件的顶部添加'use client'
。需要记住的一件事是,在真实的世界的应用程序中,您可能希望页面静态呈现,解决方案是将我们所做的封装到单独的服务器组件中,并让该服务器组件获取数据并动态呈现,而不是整个页面组件。
还涉及客户端和服务器组件之间的动态。客户端组件实际上是在服务器端预渲染的(html/css和一个小的js包),但它们也需要一个不能在服务器端运行的js负载,如果你想一想,在服务器端运行
useState
是没有意义的,因为状态存在于用户浏览器中,更不用说在服务器端有一个onClick
监听器了。当nextjs预渲染一个客户端组件时,它会发送回渲染后的html/css/server js和客户端js负载,这些都需要在客户端执行。另一方面,服务器组件不需要客户端的js,所以只返回html/css和一个小的js。在最初的示例中,getServerSideProps
是在服务器上执行的,但<About />
组件有一个客户端负载,就像带有新应用程序文件夹路由器的use client
组件一样。目前不支持在服务器中100%呈现带有客户端代码(如useState
和onClick
)的组件,这没有任何意义。关于html和css,正如我之前所说的,它最初也是在客户端组件的服务器中预呈现的。你可以在这里阅读更多关于它的信息https://nextjs.org/docs/getting-started/react-essentials#client-components