useSyncExternalStore API 与参数
学习 subscribe、getSnapshot 和 getServerSnapshot 参数,以及它们必须提供的保证。
useSyncExternalStore API 与参数 是 CoddyKit 上的免费 React Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
三个参数概览
useSyncExternalStore 最多接受三个参数:订阅、getSnapshot,以及可选的 getServerSnapshot。它们共同告诉 React 如何监听变化,以及如何读取当前值。
理解每个参数都很重要,因为使用该钩子时,参数中的细小错误是最常见的问题来源。
订阅函数
订阅函数接收 React 提供的回调,并且必须将其注册到存储库中,使该回调在存储库发生变化时运行。它必须返回一个取消订阅函数,供 React 在清理时调用。
React 通过它得知何时需要重新读取快照,因此订阅函数只负责连接和拆除变化通知。
getSnapshot 返回当前值
getSnapshot 返回存储库的当前值。React 会在渲染期间调用它来读取状态,并在收到通知后再次调用它,以检测值是否发生变化。
关键在于,当底层数据没有变化时,它必须返回引用稳定的结果:返回同一个引用,而不是每次都创建新对象。
用于 SSR 的 getServerSnapshot
可选的 getServerSnapshot 提供服务端渲染和初始水合过程中使用的值。之所以需要它,是因为仅供浏览器使用的 getSnapshot 可能依赖服务端不存在的接口。
提供它可以避免水合不匹配,因为它为服务端提供了合理的渲染值,并且与客户端最初生成的结果一致。
返回值
该钩子返回当前快照值,您可以像使用其他状态一样,直接在组件中使用它。当存储库发生变化时,React 会重新渲染,钩子也会返回更新后的快照。
从组件的角度看,这就像读取响应式状态一样,尽管真实数据源完全位于 React 之外。
getSnapshot 必须同步且保持一致
getSnapshot 必须同步运行,并且只返回根据存储库当前状态得到的值。它不应执行异步工作,也不应针对相同的底层数据产生不同结果。
React 依赖反复调用它并比较结果,因此其中的任何非确定性行为或副作用都可能导致错误行为。
不可变快照模式
持有不可变状态的存储库让 getSnapshot 变得简单,因为当前状态对象的引用只会在数据变化时改变。返回该引用即可自动获得稳定的比较结果。
这就是不可变更新模式与该钩子非常契合的原因:数据相等意味着引用相同,而 React 会跳过不必要的重新渲染。
无限循环错误
一个常见错误是在每次调用 getSnapshot 时都返回全新的对象或数组,例如在其中进行映射或筛选。React 每次都看到新引用,于是认为值发生了变化。
这会触发无限重新渲染或警告。解决方法是缓存派生值,并在源数据实际发生变化之前始终返回同一个引用。
保持快照稳定
为避免循环,请在 getSnapshot 外部计算派生数据,或将其记忆化,使该函数返回缓存的引用。许多库使用的选择器模式正是为了管理这种稳定性。
指导原则是:当存储库数据未改变时,对 getSnapshot 的两次调用必须返回完全相同的引用。
组合使用这些参数
实际使用时,您需要编写一个能够添加和移除监听器的订阅函数,一个读取稳定当前值的 getSnapshot,以及在 SSR 场景下返回服务端安全值的 getServerSnapshot。
正确实现这三个参数后,该钩子就能以极少的样板代码,为您的外部存储提供一致且并发安全的读取。
快速检查:useSyncExternalStore 参数
确定 getSnapshot 的作用。
回顾:useSyncExternalStore 接口
该钩子接受订阅、getSnapshot,以及可选的 getServerSnapshot。订阅函数负责连接监听器并返回取消订阅函数;getSnapshot 同步读取当前值,并且必须保持引用稳定;getServerSnapshot 提供适用于 SSR 的值。
经典陷阱是每次调用都返回新对象,这会导致无限循环。请缓存派生值,使未改变的数据产生相同的引用。
常见问题解答
「useSyncExternalStore API 与参数」课时是免费的吗?
是的 — 「useSyncExternalStore API 与参数」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「useSyncExternalStore API 与参数」这节课中我会学到什么?
学习 subscribe、getSnapshot 和 getServerSnapshot 参数,以及它们必须提供的保证。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「useSyncExternalStore API 与参数」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 外部存储订阅的问题
- useSyncExternalStore API 与参数
- 订阅浏览器 API
- 使用 useSyncExternalStore 构建自定义存储