React Hook 原理,及如何使用Hook

一、 Hook使用规则 

  • 只在最顶层使用Hook

  • 不要在循环,条件或嵌套函数中调用Hook;

  • 只在组件函数和自定义hook中调用Hook

Q1 : 为什么 hook 不能 在循环,条件或嵌套函数中调用Hook ? 

 A1:  因为这跟React的渲染函数和React Hook的实现原理有关,如果在循环,条件或嵌套函数中调用hook,会影响到了React自身记录的Hook顺序,会导致组件状态(值)不一致问题。

Q2: 为什么组件内,刷新了一次后,useState 仍然能保持最新的值,而不是回到初始值? 

A2:  这是因为,useState 这个hook底层逻辑是利用闭包原理,它会把最新的值,初始化的值,下一个要调用的hook这些值创建成一个fiber对象,后面每次刷新都会从这个fiber对象上获取。

     

二、 简单实现一个 useState 

demo1 : 问题在每次刷新,值都是初始化

function useState(initialValue) {var state = initialValue;function setState(newState) {state = newState;render();}return [state, setState];
}

demo2 :  问题在,如果组件内使用多个useState, _state 值会被覆盖

var _state; // 把 state 存储在外面function useState(initialValue) {_state = _state || initialValue; // 如果没有 _state,说明是第一次执行,把 initialValue 复制给它function setState(newState) {_state = newState;render();}return [_state, setState];
}

demo3:    按照hook的顺序,把state值依次存进  memoizedState  中 。

这就是为什么  hook 不能 在循环,条件或嵌套函数中调用Hook , 因为这样会影响React自身记录的Hook顺序。

let memoizedState = []; // hooks 存放在这个数组
let cursor = 0; // 当前 memoizedState 下标function useState(initialValue) {memoizedState[cursor] = memoizedState[cursor] || initialValue;const currentCursor = cursor;function setState(newState) {memoizedState[currentCursor] = newState;render();}return [memoizedState[cursor++], setState]; // 返回当前 state,并把 cursor 加 1
}

三、 真正实现一个 useState 

虽然我们用数组基本实现了一个可用的 Hooks,了解了 Hooks 的原理,但在 React 中,实现方式却有一些差异的。

  • React 中是通过类似单链表的形式来代替数组的。通过 next 按顺序串联所有的 hook。

    type Hooks = {memoizedState: any, // 指向当前渲染节点 FiberbaseState: any, // 初始化 initialState, 已经每次 dispatch 之后 newStatebaseUpdate: Update<any> | null,// 当前需要更新的 Update ,每次更新完之后,会赋值上一个 update,方便 react 在渲染错误的边缘,数据回溯queue: UpdateQueue<any> | null,// UpdateQueue 通过next: Hook | null, // link 到下一个 hooks,通过 next 串联每一 hooks
    }type Effect = {tag: HookEffectTag, // effectTag 标记当前 hook 作用在 life-cycles 的哪一个阶段create: () => mixed, // 初始化 callbackdestroy: (() => mixed) | null, // 卸载 callbackdeps: Array<mixed> | null,next: Effect, // 同上 
    };

  • memoizedState,cursor 是存在哪里的?如何和每个函数组件一一对应的?

    我们知道,react 会生成一棵组件树(或Fiber 单链表),树中每个节点对应了一个组件,hooks 的数据就作为组件的一个信息,存储在这些节点上,伴随组件一起出生,一起死亡。

参考: 

【React全解3】React.useState原理详解,一次性搞懂useState_react usestate-CSDN博客

React Hooks 原理 · Issue #26 · brickspert/blog · GitHub

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

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

相关文章

使用Kafka与Spark Streaming进行流数据集成

在当今的大数据时代&#xff0c;实时数据处理和分析已经变得至关重要。为了实现实时数据集成和分析&#xff0c;组合使用Apache Kafka和Apache Spark Streaming是一种常见的做法。本文将深入探讨如何使用Kafka与Spark Streaming进行流数据集成&#xff0c;以及如何构建强大的实…

【智慧地球】星图地球 | 星图地球超算数据工场

当前空天信息处理涉及并发并行的大量计算问题&#xff0c;需要高性能计算、智能计算联合调度&#xff0c;以此来实现多算力融合&#xff1b;而我国算力产业规模快速增长&#xff0c;超算算力资源正需要以任务驱动来统筹。 基于此&#xff0c;中科星图与郑州中心展开紧密合作&a…

从0开始python学习-39.requsts库

目录 HTTP协议 1. 请求 2. 响应 Requests库 1. 安装 2. 请求方式 2.1 requests.请求方式(参数) 2.2 requests.request() 2.3 requests.session().request() 2.4 三种方式之间的关联 3. 请求参数 3.1 params&#xff1a;查询字符串参数 3.2 data&#xff1a;Form表单…

React格式化规范

React并没有特定的格式要求&#xff0c;它允许开发者根据自己的喜好和项目需求来选择代码的格式化风格。然而&#xff0c;在React社区中有一些常见的约定和最佳实践&#xff0c;以下是一些常用的格式化规范和建议&#xff1a; 缩进&#xff1a;使用2个或4个空格来进行缩进&…

对‘float16_t’的引用有歧义

float16_t 是一个半精度浮点数类型&#xff0c;通常在一些需要高性能和低精度的场合被使用。 如果加了using namespace cv;后&#xff0c;OpenCV库中也有一个名为float16_t的类型定义&#xff0c;与最初的float16_t存在冲突&#xff0c;导致编译失败。 为了解决这个问题&#…

软件测试工程师需要掌握的理论知识(2)

11、如何处理WEB自动化测试中的跨域问题的? 。设置浏览器选项:在自动化测试中&#xff0c;可以通过设置浏览器选项来禁用跨域策略。这可以通过使用WebDriver的接口或设置浏览器选项的方法来实现。例如&#xff0c;对于Chrome浏览器&#xff0c;可以使用-disable-web-security参…

2024年全球网络安全预测报告

1.Gartner Gartners Top Strategic Predictions for 2024 and Beyond《Gartner顶级战略预测&#xff1a;2024年及未来》 https://www.gartner.com/en/articles/gartner-s-top-strategic-predictions-for-2024-and-beyond 2.IDC Top 10 Worldwide IT Industry 2024 Predict…

【Python可视化实战】钻石数据可视化

一、项目引言 1.背景和目标 钻石作为一种珍贵的宝石&#xff0c;其价格受到多种因素的影响。为了深入了解钻石价格的决定因素&#xff0c;我们收集了大量关于钻石的数据&#xff0c;并希望通过数据可视化来揭示钻石特征与价格之间的关系。 2.内容 收集钻石的各项特征数据&a…

2024 年初的大语言模型编程实践

首先我要明确&#xff0c;这篇文章并不旨在回顾大语言模型。显而易见&#xff0c;2023 年对人工智能来说是不平凡的一年&#xff0c;再去强调这一点似乎没有多大必要。这篇文章更多是作为一位程序员的个人体验分享。自从 ChatGPT 出现&#xff0c;再到使用本地运行的大语言模型…

【大数据】分布式协调系统 Zookeeper

分布式协调系统 Zookeeper 1.Zookeeper 的特点2.Zookeeper 的数据结构3.Zookeeper 的应用场景3.1 统一命名服务3.2 统一配置管理3.3 统一集群管理3.4 服务器动态上下线3.5 软负载均衡 Zookeeper 是 Apache 开源的一个顶级项目&#xff0c;目的是为分布式应用提供协调服务&#…

IO进程线程 day4

进程状态间的转化 创建出三个进程完成两个文件之间拷贝工作&#xff0c;子进程1拷贝前一半内容&#xff0c;子进程2拷贝后一半内容&#xff0c;父进程回收子进程的资源 #include <head.h> int main(int argc, const char *argv[]) {FILE *fp1NULL,*fp2NULL;//定义两个文…

【Java基础篇】常见的字符编码、以及它们的区别

常见的字符编码、以及它们的区别 ✔️ 解析✔️扩展知识仓✔️Unicode和UTF-8有啥关系?✔️有了UTF-8&#xff0c;为什么要出现GBK✔️为什么会出现乱码 ✔️ 解析 就像电报只能发出 ”滴” 和 ”答” 声一样&#xff0c;计算机只认识 0 和 1 两种字符&#xff0c;但是&#x…

【驱动序列】C#获取电脑硬件基本组合以及基础信息

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读《小5讲堂之知识点实践序列》文章。 这是2024年第7篇文章&#xff0c;此篇文章是C#知识点实践序列文章&#xff0c;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 要开发一款驱动小助手&…

vue封装基础input组件(添加防抖功能)

先看一下效果&#xff1a; // 调用页面 <template><div><!-- v-model&#xff1a;伪双向绑定 --><my-input v-model"inputVal" label"姓名" type"textarea" /></div> </template><script> import…

第3章 【例题】(完整版)

目录 前言 【例3.1】有关成绩结构体的例子 【例3.2】使用Score类的完整程序 【例 3.3】一个存在错误的程序 【例3.4】用对象赋值语句的例子 【例3.5】为类Score定义一个构造函数 【例3.6】建立对象的同时&#xff0c;用构造函数给数据成员赋初值 【例3.7】用成员初始…

ps -ef | grep 命令详解

ps 命令的作用是显示进程信息的&#xff1b; | 符号&#xff0c;是个管道符号&#xff0c;表示ps 和 grep 命令同时执行&#xff1b; grep 命令是查找&#xff08;Global Regular Expression Print&#xff09;&#xff0c;能使用正则表达式搜索文本&#xff0c;然后把匹配的…

Python实现pytest的参数化功能,使得可以在多组输入参数下运行同一个测试函数。

在pytest中&#xff0c;可以使用pytest.mark.parametrize装饰器来实现参数化功能。以下是一个示例代码&#xff1a; import pytest# 定义测试函数 def add(x, y):return x y# 使用pytest.mark.parametrize装饰器指定参数化的参数 pytest.mark.parametrize("x, y, expect…

VUE3-响应式

VUE3-响应式 响应式简介为什么使用Proxy图解实现流程DEMO实现讲解DEMO-reactiveDEMO-baseHandlerDEMO-EffectDEMO-Ref响应式简介 Vue 3引入了新的响应式系统。这个新的响应式系统使用了 ES6 的 Proxy 和 Reflect 的新特性,相对于 Vue 2.x 使用的 Observer 和 Watcher,提供了更…

Vue3如何实现组件之间的数据传递

一&#xff0c;props props可以实现父子组件通信,在vue3中我们可以通过defineProps获取父组件传递的数据。且在组件内部不需要引入defineProps方法可以直接使用&#xff01; 父组件给子组件传递数据 <Child info"我爱祖国" :money"money"></Chi…

【Spark精讲】Spark on Hive性能优化

目录 第一章 1.1 集群配置概述 1.2 集群规划概述 第二章 Yarn配置 2.1 Yarn配置说明 yarn.nodemanager.resource.memory-mb yarn.nodemanager.resource.cpu-vcores yarn.scheduler.maximum-allocation-mb yarn.scheduler.minimum-allocation-mb 第三章 Spark的配置说…