使用nextjs App Router的动态客户端渲染服务器端

bgibtngc  于 2023-05-17  发布在  其他
关注(0)|答案(1)|浏览(368)

我在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风格来获得相同的功能。谁能告诉我我错过了什么?

r55awzrz

r55awzrz1#

让我们按步骤分解:
1.你想动态地获取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]} />
}

注意,fetchcache: '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%呈现带有客户端代码(如useStateonClick)的组件,这没有任何意义。关于html和css,正如我之前所说的,它最初也是在客户端组件的服务器中预呈现的。你可以在这里阅读更多关于它的信息https://nextjs.org/docs/getting-started/react-essentials#client-components

相关问题