深入理解 React 的 useSyncExternalStore Hook
深入理解 React 的 useSyncExternalStore Hook
大家好,今天我们来聊聊 React 18 引入的一个新 Hook:useSyncExternalStore。这个 Hook 主要用于与外部存储同步状态,特别是在需要确保状态一致性的场景下非常有用。本文将深入探讨这个 Hook 的使用场景、工作原理,并通过代码示例来帮助大家更好地理解。
为什么需要 useSyncExternalStore?
在 React 18 之前,我们通常使用 useEffect 或者 useLayoutEffect 来订阅外部存储的变化。然而,这些方法有时会导致状态不一致的问题,特别是在并发模式下。useSyncExternalStore 旨在解决这些问题,确保状态在任何时候都是一致的。
基本用法
首先,我们来看一下 useSyncExternalStore 的基本用法。这个 Hook 接受三个参数:
subscribe: 一个函数,用于订阅外部存储的变化。getSnapshot: 一个函数,用于获取当前的存储快照。getServerSnapshot: 一个函数,用于在服务器端渲染时获取存储快照(可选)。
import React, { useSyncExternalStore } from "react";
// 模拟一个外部存储
const store = {
state: 0,
listeners: new Set(),
subscribe(listener) {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
},
setState(newState) {
this.state = newState;
this.listeners.forEach((listener) => listener());
},
getState() {
return this.state;
},
};
function useStore() {
return useSyncExternalStore(
store.subscribe.bind(store),
store.getState.bind(store)
);
}
function Counter() {
const state = useStore();
return (
<div>
<p>Count: {state}</p>
<button onClick={() => store.setState(state + 1)}>Increment</button>
</div>
);
}
export default Counter;
在这个示例中,我们创建了一个简单的计数器应用。store 是一个模拟的外部存储,包含状态和订阅逻辑。useStore 是一个自定义 Hook,使用 useSyncExternalStore 来订阅存储的变化并获取当前状态。
深入理解
useSyncExternalStore 的核心在于它如何确保状态一致性。它通过同步的方式获取存储快照,避免了异步更新带来的潜在问题。在并发模式下,React 可能会在渲染过程中多次调用 getSnapshot,以确保状态的一致性。
此外,useSyncExternalStore 还支持服务器端渲染。通过传递 getServerSnapshot 参数,我们可以在服务器端获取存储快照,从而避免客户端和服务器端渲染不一致的问题。
实际应用场景
useSyncExternalStore 非常适合用于以下场景:
- 全局状态管理:例如 Redux 或者 MobX,可以使用
useSyncExternalStore来订阅全局状态的变化。 - 外部数据源:例如 WebSocket 或者其他实时数据源,可以使用这个 Hook 来确保数据的一致性。
- 复杂组件通信:在一些复杂的组件通信场景下,使用
useSyncExternalStore可以简化状态管理逻辑。
代码示例:与 Redux 集成
接下来,我们来看一个与 Redux 集成的示例。假设我们有一个简单的 Redux store:
import { createStore } from "redux";
import { Provider, useSelector, useDispatch } from "react-redux";
import React, { useSyncExternalStore } from "react";
const initialState = { count: 0 };
function reducer(state = initialState, action) {
switch (action.type) {
case "INCREMENT":
return { count: state.count + 1 };
default:
return state;
}
}
const store = createStore(reducer);
function useReduxStore() {
return useSyncExternalStore(store.subscribe, store.getState, store.getState);
}
function Counter() {
const state = useReduxStore();
const dispatch = useDispatch();
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: "INCREMENT" })}>Increment</button>
</div>
);
}
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
export default App;
在这个示例中,我们创建了一个 Redux store,并使用 useSyncExternalStore 来订阅 Redux store 的变化。这样,我们可以确保组件在任何时候都能获取到最新的状态。
总结
useSyncExternalStore 是 React 18 中一个非常强大的 Hook,特别适用于需要确保状态一致性的场景。通过本文的介绍和代码示例,希望大家能够更好地理解和应用这个 Hook。如果你在项目中遇到了状态不一致的问题,不妨试试 useSyncExternalStore。
百万大学生都在用的 AI 写论文工具,篇篇无重复 : AI 写论文
深入理解 React 的 useSyncExternalStore Hook的更多相关文章
- React+DvaJS 之 hook 路由权限控制
博客 学院 下载 GitChat TinyMind 论坛 APP 问答 商城 VIP 活动 招聘 ITeye 写博客 发Chat 登录注册 原 React+DvaJS 之 hook 路由权限控制 20 ...
- 理解 React Hooks 心智模型:必须按顺序、不能在条件语句中调用的规则
前言 自从 React 推出 hooks 的 API 后,相信大家对新 API 都很喜欢,但是它对你如何使用它会有一些奇怪的限制.比如,React 官网介绍了 Hooks 的这样一个限制: 不要在循环 ...
- 深入理解React(二) —— 数据流和事件原理
版权声明:本文由左明原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/158 来源:腾云阁 https://www.qclou ...
- 深入理解React、Redux
深入理解React.ReduReact+Redux非常精炼,良好运用将发挥出极强劲的生产力.但最大的挑战来自于函数式编程(FP)范式.在工程化过程中,架构(顶层)设计将是一个巨大的挑战.要不然做出来的 ...
- 理解 React,但不理解 Redux,该如何通俗易懂的理解 Redux?
作者:Wang Namelos链接:https://www.zhihu.com/question/41312576/answer/90782136来源:知乎著作权归作者所有.商业转载请联系作者获得授权 ...
- 理解 React,但不理解 Redux,该如何通俗易懂的理解 Redux?(转)
作者:Wang Namelos 链接:https://www.zhihu.com/question/41312576/answer/90782136来源:知乎 解答这个问题并不困难:唯一的要求是你熟悉 ...
- 关于为什么使用React新特性Hook的一些实践与浅见
前言 关于Hook的定义官方文档是这么说的: Hook 是 React 16.8 的新增特性.它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性. 简单来说,就是在 ...
- 深入理解 React JS 中的 setState
此文主要探讨了 React JS 中的 setState 背后的机制,供深入学习 React 研究之用. 在课程 React.js入门基础与案例开发 中,有些同学会发现 React JS 中的 set ...
- 深度理解 React Suspense(附源码解析)
本文介绍与 Suspense 在三种情景下使用方法,并结合源码进行相应解析.欢迎关注个人博客. Code Spliting 在 16.6 版本之前,code-spliting 通常是由第三方库来完成的 ...
- 理解React组件的生命周期
本文作者写作的时间较早,所以里面会出现很多的旧版ES5的时代的方法.不过,虽然如此并不影响读者理解组件的生命周期.反而是作者分为几种不同的触发机制来解释生命周期的各个方法,让读者更加容易理解涉及到的概 ...
随机推荐
- 4G EPS 中建立 UE 与 eNB 之间的 RRC 连接
目录 文章目录 目录 前文列表 RRC 连接 Radio Bearer SRB UE 与 eNB 建立 RRC 连接的流程 前文列表 <4G EPS 中的小区搜索> <4G EPS ...
- containerd 源码分析:启动注册流程
0. 前言 containerd 是一个行业标准的容器运行时,其强调简单性.健壮性和可移植性.本文将从 containerd 的代码结构入手,查看 containerd 的启动注册流程. 1. 启动注 ...
- springcloud整合stream解决项目升级的多个消息中间件的收发问题
cloud stream (一)简介Spring Cloud Stream 是一个用来为微服务应用构建消息驱动能力的框架.它可以基于 Spring Boot 来创建独立的.可用于生产的 Spring ...
- uniapp uni-number-box组件 步长为1,还能输入小数思路分享
正常情况,输入了步长为1,是无法在输入小数的.需求是要能输入一位小数,但如果直接步长设为0.1,又不能按1这样递增,输入数量上用起来肯定很麻烦. 于是我就想了一个折中方法,步长设为:1.01,然后值改 ...
- Windows Server 2022 NTP服务器
一.配置NTP服务器 配置NTP服务器,为客户端提供时间同步服务. 如果计算机是Active Directory域控制器,则NTP服务器功能已自动启动. 因此,下面的示例是计算机在工作组环境中启用NT ...
- 轻松绕过 Graphql 接口爬取有米有数的商品数据
轻松绕过 Graphql 接口爬取有米有数的商品数据 有米有数数据的 API 接口,使用的是一种 API 查询语言 graphql.所有的 API 只有一个入口,具体的操作隐藏在请求数据体里面传输. ...
- Android 13 - Media框架(14)- OpenMax(二)
关注公众号免费阅读全文,进入音视频开发技术分享群! 这一节我们将来解析 media.codec 这个 HIDL service 究竟提供了什么服务,服务是如何启动的. 1.main 函数 我们先来看 ...
- QuickApp 快应用中 或 nodejs 中 API接品调用时 GBK转UTF8
请求接口地址:https://doc.quickapp.cn/features/system/fetch.html?h=fetch 第一步,安装包: npm install iconv-lite as ...
- Easysearch:语义搜索、知识图和向量数据库概述
什么是语义搜索? 语义搜索是一种使用自然语言处理算法来理解单词和短语的含义和上下文以提供更准确的搜索结果的搜索技术.旨在更好地理解用户的意图和查询内容,而不仅仅是根据关键词匹配,还通过分析查询的语义和 ...
- 《Android开发卷——自定义日期选择器(一)》
(小米手机) (中兴手机) 在实际开发中,Google官方提供的时间选择器API已经不能满足于我们的需要了,所以很多公司都是采用自定义的形式来实现日期选择器. 这个例子很简单,定义三个NumberPi ...