当前位置: 首页 > wzjs >正文

莱州网站建设关键字排名优化网络托管微信代运营深圳网站建设注意事项

莱州网站建设关键字排名优化网络托管微信代运营,深圳网站建设注意事项,中国网站建设公司百强,宁夏网站开发公司目录 从 Vue 到 React:深入理解 useState 的异步更新与函数式写法1. Vue 的响应式回顾:每次赋值立即生效2. React 的状态更新是异步且批量的原因解析 3. 函数式更新:唯一的正确写法4. 总结对比:Vue vs React 状态更新附录&#xf…

目录

  • 从 Vue 到 React:深入理解 useState 的异步更新与函数式写法
    • 1. Vue 的响应式回顾:每次赋值立即生效
    • 2. React 的状态更新是异步且批量的
      • 原因解析
    • 3. 函数式更新:唯一的正确写法
    • 4. 总结对比:Vue vs React 状态更新
    • 附录:React `useState` 的核心源码机制
      • 1️⃣ Hook 数据结构:链式存储的 Hook 节点
      • 2️⃣ 初次渲染:挂载阶段的 useState
      • 3️⃣ 更新过程:将 `action` 推入队列
      • 4️⃣ 更新应用:render 阶段的 `updateState`
      • 5️⃣ 函数式更新为何正确?
      • 6️⃣ 总结一下

从 Vue 到 React:深入理解 useState 的异步更新与函数式写法

在从 Vue 转向 React 的过程中,很容易被一个看似简单的问题困扰:

setCount(count + 1);
setCount(count + 1); // 预期 +2,实际只 +1?

为什么我们连续两次调用 setCount(count + 1),却没有得到我们预期的 +2 效果?而换成函数式写法:

setCount(prev => prev + 1);
setCount(prev => prev + 1); // 结果才是 +2

却又一切正常?

本文将从 Vue 的响应式系统出发,一步步理解 React 中useState 的状态更新机制,并且在文末会附上核心源码解析,帮你更深入地理解。


1. Vue 的响应式回顾:每次赋值立即生效

在 Vue 中,响应式数据是实时变更的:

const count = ref(0);
count.value++;
count.value++; // 最终为 2

Vue 是利用 Proxy 拦截 .value 的修改,每次赋值都会立即生效并触发响应式更新,从开发者来看就是所写即所得

2. React 的状态更新是异步且批量的

React 的状态更新行为则截然不同。以 useState 为例:

const [count, setCount] = useState(0);

如果我们连续两次执行:

setCount(count + 1);
setCount(count + 1);

会发现页面上 count 只增加了 1!

原因解析

React 为了性能优化,在一次事件循环中会合并所有的 setState 操作(批处理 / batching),并且这些更新是异步生效的。也就是说:

  • 多次 setCount(count + 1) 实际上使用的是同一个旧值 count
  • 每次 render 周期中,state 是只读快照,相当于每次 render 周期会给 count 拍一张照片,照片停格在 1 ,而非 2

结果就是:

const count = 0;
setCount(count + 1); // 相当于 setCount(1)
setCount(count + 1); // 还是 setCount(1)

最终只更新一次。

3. 函数式更新:唯一的正确写法

为了解决这个问题,React 提供了 函数式更新写法

setCount(prev => prev + 1);
setCount(prev => prev + 1); // 最终为 2

这种写法的优势在于:每次执行都会传入 最新的 state 值,即使处于同一个批处理中,也能逐步叠加。

它的工作方式等价于:

let current = count;
current = current + 1;
current = current + 1;
setCount(current);

4. 总结对比:Vue vs React 状态更新

特性VueReact
响应性实现Proxy 拦截或 ref()Fiber 链表 + Hook 存储
多次状态修改同步生效,立即响应异步合并更新(batch)
闭包问题很少遇到高频出现,需小心处理
正确累加方式count.value++setCount(prev => prev + 1)

附录:React useState 的核心源码机制

让我们再深入一步,了解 useState 背后是如何工作的。

useState 的底层逻辑,本质上是通过构建一个单向链表结构的 Hook 存储系统,结合更新队列与调度策略来驱动状态更新。我们从以下几个维度拆解其机制:


1️⃣ Hook 数据结构:链式存储的 Hook 节点

在 React 函数组件中,每调用一次 useState(或其他 Hook),React 就在当前组件 Fiber 节点上注册一个对应的 Hook 节点,结构大致如下:

type Hook = {memoizedState: any; // 当前 state 值queue: UpdateQueue | null; // 更新队列(待应用的 state 变更)next: Hook | null; // 指向下一个 Hook(形成链表)
}

每个组件内部维护着一个单向链表的 Hook 列表,通过「调用顺序」来标识唯一性。

⚠️ 注意:不能写条件调用 Hook(如 if (...) useState()),否则链表顺序不一致,状态错位。


2️⃣ 初次渲染:挂载阶段的 useState

在组件初次渲染时,React 调用 mountState 来创建 Hook 节点:

function mountState(initialState) {const hook = mountWorkInProgressHook();hook.memoizedState = typeof initialState === 'function'? initialState(): initialState;hook.queue = {pending: null, // 更新链表为空dispatch: null,lastRenderedReducer: basicStateReducer};const dispatch = (hook.queue.dispatch = (action) => {// 将 action 推入队列const update = {action,next: null};enqueueUpdate(hook.queue, update);scheduleRender(); // 触发调度});return [hook.memoizedState, dispatch];
}
  • hook.memoizedState:保存当前状态值
  • hook.queue:保存更新 action 的链表队列
  • dispatch:即我们使用的 setState

3️⃣ 更新过程:将 action 推入队列

当你调用 setState 时,实际发生的是:

dispatch(action);

然后内部调用:

const update = {action, // 可以是函数或值next: null
};enqueueUpdate(queue, update); // 插入环状链表
scheduleRender(); // 触发一次组件更新调度

更新队列为 循环单向链表(circular linked list),便于在 render 阶段完整遍历。


4️⃣ 更新应用:render 阶段的 updateState

组件重新渲染时,React 调用 updateState,核心逻辑如下:

function updateState() {const hook = updateWorkInProgressHook();const queue = hook.queue;let newState = hook.memoizedState;let update = queue.pending;if (update !== null) {// 进入环形队列的遍历let first = update.next;let current = first;do {const action = current.action;newState = typeof action === 'function'? action(newState) // 函数式更新(prev => next): action;current = current.next;} while (current !== first);hook.memoizedState = newState;queue.pending = null; // 清空队列}return [hook.memoizedState, queue.dispatch];
}

💡 关键点:

  • 如果 action 是函数,就使用函数式更新
  • 更新是基于前一次的 state 累加
  • 最终更新 memoizedState,用于本轮 render

5️⃣ 函数式更新为何正确?

因为 action 是一个函数,且传入的是队列中最新的 newState,每次都基于上一个结果计算:

setCount(prev => prev + 1);
setCount(prev => prev + 1); // prev 已是前一次递增后的值

这就是为什么 函数式写法可以连续叠加更新,而直接写 count + 1 会闭包住旧值。


6️⃣ 总结一下

[初始化]└─ mountState → 创建 Hook 节点并保存初始值[调用 setState]└─ dispatch(action) → enqueueUpdate() → queue 中插入更新节点[下一次 render]└─ updateState() 遍历队列 → 应用每个更新 → 更新 memoizedState[完成更新]└─ React 触发重渲 → 组件拿到新 state → UI 重新渲染

所以呢总的来说就是:

React 中每次调用 useState 实际是在组件内部构建一个 Hook 链表节点,该节点保存当前的状态值与更新队列。在调用 setState 时,更新被推入队列,在下一轮 render 时遍历这些更新并依次应用。函数式写法 setState(prev => ...) 能够正确地累加,是因为每次都基于最新的状态进行计算,这是解决闭包陷阱的核心。


http://www.dtcms.com/wzjs/600290.html

相关文章:

  • dedecms 网站地图模板网站域名解析错误怎么解决
  • 网站建设流程新闻建造网站 备案
  • 杭州模板网站做外贸哪个网站比较好2017
  • 鹤壁百度网站建设建设网站比较好的公司排名
  • 网站建设分站要备案公众号网页制作模板
  • 如何建立asp网站福田官网
  • 江门网站制作软件mysql 网站登录密码
  • 网络营销就是建立企业网站浙江建设厅网站怎么进不去
  • 做正规网站有哪些成都网站
  • 建设规范文件在哪个网站发布一流的网站建设推广
  • 水利厅网站集约化建设梵克雅宝项链官网价格图片
  • 网站制作公司商丘市大学思政类网站建设
  • 触屏手机网站建网站的策划方案
  • 婚恋网站的架构建设网站公司兴田德润i优惠吗
  • 如何做自己的播报网站雄安建设集团 网站
  • led网站建设上海服装外贸公司有哪些
  • 网站建设赛车商务网站建设实验书
  • 购物网站为什么做移动端做流量网站
  • 媒体平台化网站建站 优化推广
  • 青岛专门做网站的公司一个网站做三页是什么意思
  • 平面设计师必备网站建设工程价款结算暂行办法
  • 快递业务服务网站建设的需求分析100个免费推广网站
  • 聊城市建设局网站首页wordpress米表插件
  • 网站建设电子商务网站的留言板怎么做
  • 怎么做农家乐联盟网站wordpress 画面做成
  • 做服装有哪些好的网站有哪些网站建设与维护合同
  • 怀化公司做网站开发公司工程部
  • 汽车配件网站模板黄石市新闻
  • 东四网站建设辽宁住房和城乡建设网站
  • 网站建设情况简介虚拟主机装2个wordpress