【React】hooks的原理

2023-11-12

https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e

参考了这篇文章,对hooks的实现有初步的了解,具体的还是得研究一下官方的,这篇文章用了一个简单的方式和代码去介绍React的hooks是如何实现的。

平时我们经常使用的Hook是useState()

通过其的一个简单实例

function RenderFunctionComponent() {
  const [firstName, setFirstName] = useState("Rudi");
  const [lastName, setLastName] = useState("Yardley");

  return (
    <Button onClick={() => setFirstName("Fred")}>Fred</Button>
  );
}

我们使用useState()通常的代码的,一般最好奇的事情就是,为什么是 

const [key, setkey] = useState()

我们更新值的话都是通过

setKey(new value)

去更新的,所以这个时候就会很懵懂其背后是怎么实现更新的。

下面借鉴上述博客中的图去理解

(1)初始化

创建两个空的数组 state 和 setters, 同时讲指针设置为0

(2)第一次渲染

在第一次运行时,会将setter函数放入setters数组,同时会记录指针现在的位置,然后讲对应的state放入state数组。

(3)后面的渲染

初始化过后,指针会初始化到0,这样做是为了可以讲每个值从数据中读出

(4)请求的处理

每一个setter对游标位置都有一个引用,所以更改state的值就是通过去调用setter从而触发其对应数组在对应位置的值

在这里其实对setters函数的作用就有一点明白了,但是这里仅仅用于理解,背后的数据结构设计应该没那么简单。

最主要可以理解的点就是state的值是不断变化的,那么其就不能固定去寻找了(要做应该也行,可能在数据结构方面的开销会更大吧,不然如果可以用一个map解决开发团队绝不会用得那么麻烦),通过一个setter函数,首先名字是固定的,其实通过指针(游标)去确定对应的state值的位置,并将其更新。

通过一段简单的代码去理解

let state = [];
let setters = [];
let firstRun = true;
let cursor = 0;

function createSetter(cursor) {
  return function setterWithCursor(newVal) {
    state[cursor] = newVal;
  };
}

// 模仿一个useState的函数
export function useState(initVal) {
  if (firstRun) {               // 判断是不是第一次渲染吧
    state.push(initVal);
    setters.push(createSetter(cursor));
    firstRun = false;
  }

  const setter = setters[cursor];
  const value = state[cursor];

  cursor++;
  return [value, setter];
}

// 使用hooks的组件代码
function RenderFunctionComponent() {
  const [firstName, setFirstName] = useState("Rudi"); // cursor: 0
  const [lastName, setLastName] = useState("Yardley"); // cursor: 1

  return (
    <div>
      <Button onClick={() => setFirstName("Richard")}>Richard</Button>
      <Button onClick={() => setFirstName("Fred")}>Fred</Button>
    </div>
  );
}

// 这是一种模拟的渲染周期
function MyComponent() {
  cursor = 0; // resetting the cursor
  return <RenderFunctionComponent />; // render
}


//下面就是不断执行代码,并得出相应的结果
console.log(state); // Pre-render: []
MyComponent();
console.log(state); // First-render: ['Rudi', 'Yardley']
MyComponent();
console.log(state); // Subsequent-render: ['Rudi', 'Yardley']

// click the 'Fred' button

console.log(state); // After-click: ['Fred', 'Yardley']

在这个模拟的过程中,不难发现,每次都是重新去变量setter和state的数组,虽然这个仅仅只是为了更好的理解,但是在渲染方面还是有点值得思路的,就是按道理应该每次重新渲染不是全部渲染,应该是局部的,这个感觉涉及到内部的匹配算法了。

但是通过上面,可以初步理解整一个过程其是大概怎么实现,同时在写代码的时候不会觉得很奇怪

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【React】hooks的原理 的相关文章

随机推荐

  • 华为云服务器免费用,CDN免费用,数据库免费用,免费免费,全场免费

    华为云免费专区 全场免费 自从华为云17年进军公有云市场以来 市场份额增长神速 20年华为云以高达259 6 的同比增长速度 已然稳定公有云市场前三的位置 但很多人依然没有试用过华为云的产品 即便性价比很高 也不敢贸然更换厂商 俗话说是骡子
  • 【ubuntu】Anaconda 安装+环境配置:pytorch1.5.0+torchvision0.6.0+cudatoolkit10.1

    1 正确安装anaconda 1 下载对应Anaconda版本 以Anaconda3 5 3 1 Linux x86 64 sh为例 Anaconda下载连接 2 命令安装 bash Anaconda3 5 3 1 Linux x86 64
  • C语言文件详解(超级详细,记得收藏~~~)

    什么是文件 磁盘上的文件是文件 在程序设计中 我们一般读的文件有两种 程序文件 和 数据文件 程序文件包括源程序文件 后缀为 c 目标文件 win下后缀为 obj 可执行文件 win下环境后缀为 exe 数据文件 文件的内容不一定是程序 而
  • java oauth2登录以及权限_OAuth2实现单点登录SSO

    1 前言 技术这东西吧 看别人写的好像很简单似的 到自己去写的时候就各种问题 一看就会 一做就错 网上关于实现SSO的文章一大堆 但是当你真的照着写的时候就会发现根本不是那么回事儿 简直让人抓狂 尤其是对于我这样的菜鸟 几经曲折 终于搞定了
  • WebSocket和HTTP的区别及原理

    HTTP协议 HTTP是单向的 客户端发送请求 服务器发送响应 举例来说 当客户端向服务器发送请求时 该请求以HTTP或HTTPS的形式发送 在接收到请求后 服务器会将响应发送给客户端 每个请求都与一个对应的响应相关联 在发送响应后客户端与
  • Jni基础

    1 JNI 的一般开发流程 1 1 定义好本地的 native 方法 package com darren ndk day13 import java util UUID public class Simple1 public static
  • 【转码方式】-Base64

    Base64 作用 在数据传输过程中 如果报文中存在英文字母以外的字符 就会出现乱码 如中文 图片 或者二进制报文 此时就可以通过Base64将不规则的数据流转化成Base64规定的64个可打印的字符 提高数据的可读性和可打印性 转码原理
  • c++实现合并两个无序数组并以从大到小的顺序排序

    今天做了一下途游游戏的线上笔试题 题目中有一个是合并两个无序数组并排序 从大到小 在这里写一下我的思路 如果有更简单思路的大神请给我留言 我首先想到的一个思路就是把A和B先放在同一个数组里 在随便用一个排序算法对新数组进行排序 这个方法时间
  • Shell脚本中2>&1、>、>>等符号到底是什么含义

    场景 在Linux Shell命令中 我们经常会遇到命令中类似这样的 gt 2 gt 1 符号 那么这些符号是什么含义 有什么用处呢 下面一起来看下 概念 在Linux shell中 0 1 2代表文件描述符 名称 代码 操作符 Java中
  • C++多种解法求最大回文子串

    题目 给定一字符串 求最长的回文子串 解法一 暴力法 循环查找字符串中的所有回文子串 时间复杂度O N3 第一遍循环 选取开始点 i 第二遍循环 选取结束位置 j 第三遍循环 判断 i j 是否为回文字符串 int palindromeA
  • Mysql服务器的外部连接

    目录 前言 Windows上的客户端连接工具有 Linux上连接其他虚拟机上的MySQL服务器 在Windows上通过Navicat连接虚拟机上的Mysql服务器 1 我们先下载好Navicat 2 当我们下载安装好Navicat后 打开它
  • 用org.apache.tools.zip压缩/解压缩zip文件

    package org coolyongzi import java io File import java io FileInputStream import java io FileOutputStream import java io
  • android删除文件夹代码,Android 删除指定文件代码

    package com tware pdfdrop import java io File import android app Activity import android graphics Color import android o
  • LLVM系列第十五章:写一个简单的中间代码生成器IR Generator

    系列文章目录 LLVM系列第一章 编译LLVM源码 LLVM系列第二章 模块Module LLVM系列第三章 函数Function LLVM系列第四章 逻辑代码块Block LLVM系列第五章 全局变量Global Variable LLV
  • 关于2023美赛ABCDEF各题的选题

    本文是关于2023美赛各题的选题以及思路分析 占个位置 比赛开始后会在本帖实时更新赛题思路代码 文章末尾获取 持续为更新参考思路 赛题思路 会持续进行思路模型分析 下自行获取 A题思路 比赛开始后第一时间更新 B题思路 比赛开始后第一时间更
  • Qt 控件尺寸设置

    一 运行无误 Qt 的控件在显示时 有时运行没有问题 但是会有以下信息 QWindowsWindow setGeometry Unable to set geometry 247x97 1200 801 frame 273x168 1187
  • 【python、pycharm安装教程】python3.7和pycharm2019最详细安装教程

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 python3 7和pycharm2019最详细安装教程 一 安装python 二 安装Pycharm 安装路径中不要存在中文 一 安装python 1 双击运行python
  • java 根据word文档模板导出word

    1 创建word模板 2 动态数据占位 格式 xxxxx 3 点击另存为xml格式 4 修改后缀名为ftl 5 导入到idea中 6 修改文件编码为utf 8 7 复制模板内容在线代码格式化 8 编辑模板中内容 如果有空值会报错 可以 xx
  • R-应用流行病学和公共卫生-5.导入

    rio包 我们推荐的 R 包是 rio 名称 rio 是 RI O 输入 输出 的缩写 它的功能import 和export 可以处理许多不同的文件类型 例如 xlsx csv rds tsv 当您提供这些函数的文件路径 包括 csv 之类
  • 【React】hooks的原理

    https medium com ryardley react hooks not magic just arrays cd4f1857236e 参考了这篇文章 对hooks的实现有初步的了解 具体的还是得研究一下官方的 这篇文章用了一个简