菜单

服务器端渲染

相关源文件

本文档介绍了如何在 Next.js 等服务器端渲染 (SSR) 框架中使用 Zustand。它涵盖了 SSR 环境中全局状态管理的挑战、每个请求的 store 创建、正确的 hydration 技术以及防止常见问题的最佳实践。有关 Next.js 集成的更多详细信息,请参阅 Next.js 设置

1. 理解 Zustand 的 SSR 挑战

服务器端渲染为 Zustand 等状态管理库带来了独特的挑战。由于 Zustand store 通常作为模块级别的单例创建,它们可能在服务器端渲染环境中引起问题,在这些环境中:

  1. 服务器处理多个并发请求
  2. 应用程序渲染两次(服务器端和客户端)
  3. 服务器端渲染和客户端渲染之间可能发生 hydration 不匹配

来源:docs/guides/ssr-and-hydration.md6-10 docs/guides/nextjs.md13-22

2. Zustand 的核心 SSR 原则

在使用 Zustand 进行 SSR 时,您需要遵循以下核心原则:

  1. 为每个请求创建 store:避免不同用户请求之间的状态共享
  2. 正确的 hydration:确保服务器和客户端渲染相同的初始状态
  3. 隔离:将 store 创建保留在组件级别,而不是模块级别

来源:docs/guides/nextjs.md26-33 docs/guides/ssr-and-hydration.md91-97

3. 每个请求的 Store 创建模式

为防止状态在请求之间泄露,请实施每个请求的 store 创建模式:

3.1 使用 `createStore` 的 vanilla store

推荐的方法是使用 `zustand/vanilla` 中的 `createStore` 来创建一个 store 工厂:

来源:docs/guides/nextjs.md72-98 docs/guides/nextjs.md106-149

3.2 Store Provider 组件

Store 创建模式通常使用包含以下关键元素的 provider 组件:

  1. 一个创建新 store 实例的 store 工厂函数
  2. 一个用于持有 store 引用的 React context
  3. 一个 `useRef` 以确保 store 在每个组件生命周期中仅创建一次
  4. 用于安全访问 store 状态的自定义 hook

此模式避免了模块级别的 store 实例,这些实例会在请求之间共享

来源:docs/guides/nextjs.md106-149

4. 框架特定实现

4.1 Next.js App Router

在 Next.js App Router 中,请遵循以下最佳实践:

  1. 将 `'use client'` 指令添加到所有使用 Zustand 的组件中
  2. 将所有 Zustand 逻辑隔离在客户端组件中
  3. 切勿在 React Server Components 中访问 store 状态
  4. 将 store provider 放在客户端布局组件中

典型文件结构

来源:docs/guides/nextjs.md320-402

4.2 Next.js Pages Router

在 Next.js Pages Router 中,请使用以下模式:

  1. 使用 `createStore` 创建您的 store
  2. 在 `_app.tsx` 或页面组件中添加 store provider
  3. 创建自定义 hook 来访问 store 状态

来源:docs/guides/nextjs.md254-317

5. 防止 Hydration 不匹配

当服务器和客户端渲染不同的内容时,会发生 Hydration 不匹配,这会导致 React 警告或错误。

5.1 Hydration 不匹配的常见原因

来源:docs/guides/ssr-and-hydration.md188-197

5.2 最佳实践

  1. 一致的初始化:在服务器和客户端上使用相同的初始状态
  2. 避免在渲染中使用浏览器 API:不要在渲染逻辑中使用 `window` 或其他仅限浏览器的 API
  3. 静态初始状态:在可能的情况下,为初始状态使用静态值
  4. `useEffect` 用于仅客户端代码:在 `useEffect` 中初始化依赖于浏览器的状态,而不是在渲染期间

6. 用于测试的 Store 重置

在测试 SSR 应用程序时,您通常需要在测试之间重置 store。此模式创建一个函数,用于将 store 重置为其初始状态:

来源:docs/guides/testing.md84-149 docs/guides/how-to-reset-state.md44-68

7. 完整示例

以下是支持 SSR 的 Zustand store 的完整示例:

  1. Store 创建 - 使用 factory 模式创建 vanilla store
  2. Context Provider - 创建并提供 store 的组件
  3. 自定义 Hook - 用于从组件访问 store 的 Hook

这些组件共同确保:

  • 每个请求在服务器上都获得自己的 store 实例
  • Store 在客户端上被正确初始化和 hydration
  • 组件可以通过一致的 API 访问 store 状态

来源:docs/guides/nextjs.md72-98 docs/guides/nextjs.md106-149 docs/guides/nextjs.md322-346