千家信息网

怎么学习React Hooks原理

发表于:2024-10-12 作者:千家信息网编辑
千家信息网最后更新 2024年10月12日,这篇文章主要介绍"怎么学习React Hooks原理",在日常操作中,相信很多人在怎么学习React Hooks原理问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"怎么学
千家信息网最后更新 2024年10月12日怎么学习React Hooks原理

这篇文章主要介绍"怎么学习React Hooks原理",在日常操作中,相信很多人在怎么学习React Hooks原理问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"怎么学习React Hooks原理"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

为什么要学习 React Hooks 原理

首先,功利点来说:目前前端框架三分天下:React、Vue、Angular,而 React 自从 v16.8.0 版本正式推出 React Hooks 概念后,风势已经从原来的类组件猛地转向函数组件,这是一个在设计模式、心智模型层次,且非常近期的革新,因此只要是你谈到自己会 React ,就一定会在面试中被问到 React Hooks 的原理。

再者,从实际角度出发,了解 React Hooks 原理对我们日常开发调试都有莫大的好处;我们可以认识到 React Hooks 其实也并不是什么黑魔法,我们在开发中碰到的奇奇怪怪的问题,只不过是我们还没有掌握 React Hooks 导致的,也不需要用一些 tricky 的方法来解决。

useState / useReducer

useState 和 useReducer 都是关于状态值的提取和更新,从本质上来说没有区别,从实现上,可以说 useState 是 useReducer 的一个简化版,其背后用的都是同一套逻辑。

React Hooks 如何保存状态

React 官方文档中有提到,React Hooks 保存状态的位置其实与类组件的一致;翻看源码后,我发现这样的说法没错,但又不全面:

  • 两者的状态值都被挂载在组件实例对象FiberNode的memoizedState属性中。

  • 两者保存状态值的数据结构完全不同;类组件是直接把 state 属性中挂载的这个开发者自定义的对象给保存到memoizedState属性中;而 React Hooks 是用链表来保存状态的,memoizedState属性保存的实际上是这个链表的头指针。

下面我们来看看这个链表的节点是什么样的 —— Hook 对象:

// react-reconciler/src/ReactFiberHooks.js  export type Hook = {    memoizedState: any, // 最新的状态值    baseState: any, // 初始状态值,如`useState(0)`,则初始值为0    baseUpdate: Update | null,    queue: UpdateQueue | null, // 临时保存对状态值的操作,更准确来说是一个链表数据结构中的一个指针    next: Hook | null,  // 指向下一个链表节点  };

官方文档一直强调 React Hooks 的调用只能放在函数组件/自定义 Hooks 函数体的顶层,这是因为我们只能通过 Hooks 调用的顺序来与实际保存的数据结构来关联:

PS:虽然上面一致都是以 useState 和 useReducer 来作为例子说明,但实际上所有 React Hooks 都是用这种链表的方式来保存的。

React Hooks 如何更新状态

熟悉 useState API 的话,我们都知道怎么去更新状态:

const [name, setName] = useState('')  setName('张三')

那么,由 useState 返回的这个用来更新状态的函数(下文称为 dispatcher),运行的原理是怎么样的呢?

当我们在每次调用 dispatcher 时,并不会立刻对状态值进行修改(对的,状态值的更新是异步的),而是创建一条修改操作——在对应 Hook 对象的queue属性挂载的链表上加一个新节点:

在下次执行函数组件,再次调用 useState 时, React 才会根据每个 Hook 上挂载的更新操作链表来计算最新的状态值。你也许会好奇,为什么要把更新操作都保存起来呢,只保存最新的一次更新操作不就行了吗?你会这样想,大概是忘了 useState 支持这样的语法了吧:

const [name, setName] = useState('')  setName(name => name + 'a')  setName(name => name + 'b')  setName(name => name + 'c')  // 下次执行时就可以得到 name 的最新状态值为'abc'啦

useEffect

useEffect 的保存方式与 useState / useReducer 类似,也是以链表的形式挂载在FiberNode.updateQueue中。

下面我们按 mount 和 update 这两个组件生命周期来阐述 useEffect 的执行原理:

mount 阶段:mountEffect

根据函数组件函数体中依次调用的 useEffect 语句,构建成一个链表并挂载在FiberNode.updateQueue中,链表节点的数据结构为:

 const effect: Effect = {      tag, // 用来标识依赖项有没有变动      create, // 用户使用useEffect传入的函数体      destroy, // 上述函数体执行后生成的用来清除副作用的函数      deps, // 依赖项列表      next: (null: any),  };

组件完成渲染后,遍历链表执行。

update 阶段:updateEffect

同样在依次调用 useEffect 语句时,判断此时传入的依赖列表,与链表节点Effect.deps中保存的是否一致(基本数据类型的值是否相同;对象的引用是否相同),如果一致,则在Effect.tag标记上NoHookEffect。

执行阶段

在每次组件渲染完成后,就会进入 useEffect 的执行阶段:function commitHookEffectList():

  1. 遍历链表

  2. 如果遇到Effect.tag被标记上NoHookEffect的节点则跳过。

  3. 如果Effect.destroy为函数类型,则需要执行该清除副作用的函数(至于这Effect.destroy是从哪里来的,下面马上说到)

  4. 执行Effect.create,并将执行结果保存到Effect.destroy(如果开发者没有配置return,那得到的自然是undefined了,也就是说,开发者认为对于当前 useEffect 代码段,不存在需要清除的副作用);注意由于闭包的缘故,Effect.destroy实际上可以访问到本次Effect.create函数作用域内的变量。

我们重点请注意到:是先清除上一轮的副作用,然后再执行本轮的 effect 的。

其它 React Hooks Api

其它的的 React Hooks Api ,其实也差不多是这样的原理:用链表数据结构来做全局状态保持;判断依赖项决定是否要更新状态等等,这里不再累述。

到此,关于"怎么学习React Hooks原理"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

状态 函数 组件 原理 状态值 学习 更新 数据 节点 实际 对象 属性 数据结构 结构 开发 一致 副作用 阶段 实际上 开发者 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 信用基础数据库管理 天刀手游 服务器已满 贵阳中小学举办网络安全教育活动 目前人数最多的tbc服务器 高景网络技术上海有限公司 用什么软件开发app最轻松 公路管理软件开发 360关注网络安全 网络安全行为学 撤销软件开发许可是什么意思 基层干部网络安全知识 阿里服务器迁移华为云 软件开发售后会不会半夜工作 重庆海通证券公司网络技术 域名服务器上存放主机的 美国基础教育网络安全法案 负责监控数据库系统的人 期货软件开发 案例 云帮手能加几个服务器 网络安全服务内容清单 2015网络安全前景 服务器产业链的未来到底看什么 网络安全 工作总结 网络安全对于大学生的重要性 数据库学生成绩管理系统项目简介 网站开发软件开发商 重庆海通证券公司网络技术 实验室网络安全微视频 深圳蚂蚁互联网科技 网络安全和保密会讲话
0