【前端面试】看react源码,解读useState

点击:react git 链接

截止2024.8.22最新版本如下在这里插入图片描述

React hooks

源码好深,hook封装位于packages/react-reconciler/src/ReactFiberHooks.js

hook的数据类型:

export type Hook = {memoizedState: any,baseState: any,baseQueue: Update<any, any> | null,queue: any,next: Hook | null,
};

HooksDispatcher

在 React 18 及更新的版本中,HooksDispatcher 是一个内部使用的调度器,它负责协调 React 组件的挂载(mount)和更新(update)过程中的 Hooks 调用。HooksDispatcherOnMountHooksDispatcherOnUpdateHooksDispatcher 在不同渲染阶段的实例,它们分别用于处理组件首次挂载和随后的更新。
HooksDispatcherOnMountHooksDispatcherOnUpdate 是 React 为了更好地控制组件渲染过程中 Hooks 的行为而引入的内部调度器实例。它们确保了 Hooks 在组件的不同生命周期阶段能够正确地执行。

HooksDispatcherOnMount

  • HooksDispatcherOnMount 是在组件首次挂载时使用的调度器实例。
  • 在这个阶段,React 会调用组件内的所有 Hooks,例如 useState, useEffect, useContext 等,并且是按照它们在代码中出现的顺序进行调用。
  • 由于是首次渲染,useState 会为每个 state 创建初始状态,useEffect 会执行所有 effect 的逻辑(但不会清除,因为没有之前的 effect)。
    在这里插入图片描述

HooksDispatcherOnUpdate

  • HooksDispatcherOnUpdate 是在组件更新时使用的调度器实例。
  • 在更新阶段,React 同样会调用组件内的所有 Hooks,但这次调用是有条件的。React 会根据调度器来判断 Hooks 是否需要被调用。
  • 例如,useState 会返回当前的状态值,useEffect 会根据 effect 的依赖项来决定是否执行 effect。
  • 更新阶段的 Hooks 调用通常涉及到比较前后的状态或 props,以确定是否需要执行某些操作或副作用。
    在这里插入图片描述

为什么需要不同的调度器实例?

  • 性能优化:通过在不同的渲染阶段使用不同的调度器实例,React 可以更精确地控制 Hooks 的行为,从而优化性能。
  • 避免副作用的重复执行:在更新阶段,React 需要区分哪些副作用需要重新执行,哪些可以保持不变。
  • 保持渲染的一致性:确保组件的渲染行为在不同的渲染阶段保持一致性。

useState解析

useState解析-mountState

mountState就是useState的实现,间接调用了mountStateImpl、mountWorkInProgressHook。下面展开详细解读

mountWorkInProgressHook

  • 拿到当前FiberNode的workInProgressHook变量(可以将其理解为hooks链表的指针),将其指向当前最新hook,并返回引用。
  • currentlyRenderingFiber.memoizedState指向hooks链表的头指针。

function mountWorkInProgressHook(): Hook {const hook: Hook = {memoizedState: null,baseState: null,baseQueue: null,queue: null,next: null,};if (workInProgressHook === null) {// This is the first hook in the listcurrentlyRenderingFiber.memoizedState = workInProgressHook = hook;} else {// Append to the end of the listworkInProgressHook = workInProgressHook.next = hook;}return workInProgressHook;
}

通过调用,先将hook挂在到filber node的hooks链表上
计算传入的初始值,并赋值给hook.memoizedState
给hook.queue 赋初值。创建一个新的链表作为更新队列,用来存放更新(setXxx())

function mountStateImpl<S>(initialState: (() => S) | S): Hook {const hook = mountWorkInProgressHook();if (typeof initialState === 'function') {const initialStateInitializer = initialState;// $FlowFixMe[incompatible-use]: Flow doesn't like mixed typesinitialState = initialStateInitializer();if (shouldDoubleInvokeUserFnsInHooksDEV) {setIsStrictModeForDevtools(true);// $FlowFixMe[incompatible-use]: Flow doesn't like mixed typesinitialStateInitializer();setIsStrictModeForDevtools(false);}}hook.memoizedState = hook.baseState = initialState;const queue: UpdateQueue<S, BasicStateAction<S>> = {pending: null,lanes: NoLanes,dispatch: null,lastRenderedReducer: basicStateReducer,lastRenderedState: (initialState: any),};hook.queue = queue;return hook;
}

创建一个 dispatch 示例方法(即 useState 返回的数组的第二个参数:setXxx()),
该方法的作用是用来修改 state,并将此更新添加到更新队列中,通过 .bind 把当前 fiber node、更新队列、 dispatch 方法关联起来:


function mountState<S>(initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {const hook = mountStateImpl(initialState);const queue = hook.queue;const dispatch: Dispatch<BasicStateAction<S>> = (dispatchSetState.bind(null,currentlyRenderingFiber,queue,): any);queue.dispatch = dispatch;return [hook.memoizedState, dispatch];
}

综上,useState 在 Mount (组件初始化)阶段:

  1. 获取当前 Hook 节点,同时将当前 Hook 添加到 Hook 链表中
  2. 初始化 Hook 的状态,即读取初始 state 值
  3. 创建一个新的链表作为更新队列,用来存放更新操作setXxx(),

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/406828.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构(6.2_4)——图的基本操作

注&#xff1a;只探讨邻接矩阵和邻接表怎么实现图的基本操作 Adjacent(G,x,y):判断图G是否存在边<x,y>或(x,y) 领接矩阵 邻接表 有向图&#xff1a; Neighbors(G,x):列出图G中与结点x邻接的边 有向图 InsertVertex(G,x):在图G中插入顶点x DeleteVertex(G,x):在图G中删除…

软件测试-测试分类

测试分类 按照测试目标测试 界面测试 页面内展示的所有内容/元素都需要测试 参考UI图找不同 功能测试 ​ 如何设计功能测试用例&#xff1f; 参考产品规格说明书进行用例的编写&#xff0c;具体的测试用例需要使用黑盒设计测 试用例的方法&#xff0c;如等价类、边界值、…

深入浅出链表

目录 1.链表的基本概念及结构 1.1基本概念 1.2结构 2.链表的分类 3.链表的实现&#xff08;循环链表增删查改实现&#xff09; 1.动态申请节点&#xff08;结点&#xff09;​编辑 2.单链表打印 3.单链表尾插 4.单链表头插 5.单链表尾删 6.单链表头删 7.单链表查找 …

如何应对突发技术故障和危机:开发团队的应急策略

开发团队如何应对突发的技术故障和危机&#xff1f; 在数字化时代&#xff0c;软件服务的稳定性对于企业至关重要。然而&#xff0c;即使是大型平台&#xff0c;如网易云音乐&#xff0c;也可能遇到突发的技术故障。网页端出现502 Bad Gateway 报错&#xff0c;且App也无法正常…

亚信科技转型持久战:扎根行业大模型,深耕行业数字化

有人说&#xff1a;“AI大模型时代&#xff0c;每个行业和产品都值得重新做一遍。” 深以为然。自大模型2023年迅速崛起以来&#xff0c;AI技术不断取得突破&#xff0c;并开始深刻影响多个领域。这其中&#xff0c;AI大模型如何从通用走向垂直行业成为当下产业界最为关心的话…

45+用户占比近30%,网文产业如何赋能IP长链?

网文市场加速发展&#xff0c;巨头抢占中老年用户 作者&#xff5c;吕娆炜 排版&#xff5c;张思琪 干货抢先看 1. 我国网文产业市场规模突破3000亿元&#xff0c;在用户方面&#xff0c;截至2023年底&#xff0c;我国网文用户数量达5.37亿&#xff0c;同比增长9%&#xff0c…

【机器学习】线性回归

一、什么是回归 分类任务很好理解&#xff0c;比如去银行贷款&#xff0c;银行会根据贷款人的年龄、工资&#xff08;特征&#xff09;去决定贷款&#xff08;标签1&#xff09;和不贷款&#xff08;标签0&#xff09;。而回归任务&#xff0c;是预测允许贷款的额度&#xff08…

【学习笔记】灰色预测 GM(1,1) 模型 —— Matlab

文章目录 前言一、灰色预测模型灰色预测适用情况GM (1,1)模型 二、示例指数规律检验(原始数据级比检验)级比检验的定义GM(1,1) 模型的级比检验 模型求解求解微分方程 模型评价(检验模型对原始数据的拟合程度)残差检验级比偏差检验 三、代码实现----Matlab级比检验代码模型求解代…

0成本学习Liunx系统【只需要一台笔记本电脑,无需购买云服务器】

【准备工作&#xff0c;需要软件】&#xff1a; 1&#xff1a;MobaXterm 【服务器连接工具&#xff08;免费开源&#xff09;】 2&#xff1a;CentOS-7-x86_64-DVD-2009.iso 【CentOS-7 镜像】 3&#xff1a;VirtualBox-7.0.20-163906-Win.exe 【虚拟机壳子】 4&…

20 动态内存管理

目录 一、为什么要有动态内存管理 二、malloc 和 free &#xff08;一&#xff09;malloc &#xff08;二&#xff09;free 三、calloc 和 realloc &#xff08;一&#xff09;calloc &#xff08;二&#xff09;realloc 四、常见的动态内存错误 &#xff08;一&#…

前端本地代理配置方式

Whistle 介绍 Whistle 是一个基于 Node.js 的跨平台 Web 调试工具。允许捕获、查看和修改 HTTP/HTTPS 网络请求。通过使用 Whistle&#xff0c;可以轻松地进行接口代理、抓包、模拟数据、修改请求和响应等操作&#xff0c;以便在前端开发中调试网络请求。 Proxy SwitchyOmega…

133-横向移动域控提权NetLogonADCSPACKDC永恒之蓝

除了前面讲到的口令密码进行横向移动&#xff0c;还存在使用系统漏洞进行的横向移动的方式&#xff0c;本节课就是讲一些域内系统的漏洞&#xff0c;主要是域控提权的一些漏洞 1、横向移动-系统漏洞-CVE-2017-0146&#xff08;ms17-010&#xff0c;永恒之蓝&#xff09; 2、横…

Java之迭代器的使用

Java之迭代器的使用 摘要基础知识List迭代器Map迭代器 摘要 本博客主要讲解容器的迭代器的使用&#xff0c;包括List、Set和Map等容器 基础知识 这是类的继承关系图 迭代器的原理(一开始迭代器并不指向任何有效元素)&#xff1a; List迭代器 public class TestIterator …

World of Warcraft [CLASSIC] the Eye of Eternity [EOE] P1-P2

World of Warcraft [CLASSIC] the Eye of Eternity [EOE] 永恒之眼&#xff08;蓝龙&#xff09; 第一阶段 第二阶段 第三阶段 载具1-6技能介绍 World of Warcraft [CLASSIC] the Eye of Eternity [EOE]_永恒之眼 eoe-CSDN博客 永恒之眼怎么出副本呢&#xff0c;战斗结束&am…

【Java】/* 链式队列 和 循环队列 - 底层实现 */

一、链式队列 1. 使用双向链表实现队列&#xff0c;可以采用尾入&#xff0c;头出 也可以采用 头入、尾出 (LinkedList采用尾入、头出) 2. 下面代码实现的是尾入、头出&#xff1a; package bageight;/*** Created with IntelliJ IDEA.* Description:* User: tangyuxiu* Date: …

windows安装android studio

下载 https://developer.android.google.cn/studio?hlzh-cn 安装 打开cmd输入如下命令 android-studio-2024.1.1.12-windows.exe /NCRC 注意 运行命令后可能还报错&#xff0c;但是会出现弹窗 如果还是报错可以选择zip 运行 不设置代理 等待下载即可&#xff0c;…

Linux云计算 |【第二阶段】SECURITY-DAY3

主要内容&#xff1a; Prometheus监控服务器、Prometheus被监控端、Grafana监控可视化 补充&#xff1a;Zabbix监控软件不自带LNMP和DB数据库&#xff0c;需要自行手动安装配置&#xff1b;Prometheus监控软件自带WEB页面和DB数据库&#xff1b;Prometheus数据库为时序数据库&…

Android 14适配

最近刚刚做了Android 14的适配&#xff08;即targetSdkVersion 升级到 34 &#xff09;&#xff0c;通过此博客整理下相关注意点。 前台服务类型 当targetSdkVersion > 34 &#xff0c;应用内的前台服务&#xff08;Foreground Service&#xff09;需要指定至少一种前台服务…

k8s - Secret实践练习

参考文档&#xff1a;https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/ 这个和ConfigMap很相似&#xff0c;这里选两个做下测试&#xff0c;就不过多赘述了 简介 Secret 类似于 ConfigMap 但专门用于保存机密数据。 Secret 是一种包含少量敏感信息例如密码…

qt creator自动运行单元测试

qt creator自动运行单元测试 工具-选项-Testing-General&#xff0c;找到Automatically run&#xff0c;选项卡选择All。