当前位置:   article > 正文

React-Hooks源码深度解读_解析ahooks代码

解析ahooks代码

useState 解析

useState 使用

通常我们这样来使用 useState 方法,

function App() {
   
  const [num, setNum] = useState(0);
  const add = () => {
   
    setNum(num + 1);
  };
  return (
    <div>
      <p>数字: {
   num}</p>
      <button onClick={
   add}> +1 </button>
    </div>
  );
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

useState 的使用过程,我们先模拟一个大概的函数

function useState(initialValue) {
   
  var value = initialValue
  function setState(newVal) {
       
    value = newVal
  }
  return [value, setState]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这个代码有一个问题,在执行 useState 的时候每次都会 var _val = initialValue,初始化数据;

于是我们可以用闭包的形式来保存状态。

const MyReact = (function() {
   
   // 定义一个 value 保存在该模块的全局中
  let value
  return {
   
    useState(initialValue) {
   
      value = value || initialValue 
      function setState(newVal) {
   
        value = newVal
      }
      return [value, setState]
    }
  }
})()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这样在每次执行的时候,就能够通过闭包的形式 来保存 value。

不过这个还是不符合 react 中的 useState。因为在实际操作中会出现多次调用,如下。

function App() {
   
  const [name, setName] = useState('Kevin');
  const [age, setAge] = useState(0);
  const handleName = () => {
   
    setNum('Dom');
  };
  const handleAge = () => {
   
    setAge(age + 1);
  };
  return (
    <div>
      <p>姓名: {
   name}</p>
      <button onClick={
   handleName}> 改名字 </button>
       <p>年龄: {
   age}</p>
      <button onClick={
   handleAge}> 加一岁 </button>
    </div>
  );
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

因此我们需要在改变 useState 储存状态的方式

useState 模拟实现

const MyReact = (function() {
   
  // 开辟一个储存 hooks 的空间
  let hooks = []; 
  // 指针从 0 开始
  let currentHook = 0 
  return {
   
    // 伪代码 解释重新渲染的时候 会初始化 currentHook
    render(Component) {
   
      const Comp = Component()
      Comp.render()
      currentHook = 0 // 重新渲染时候改变 hooks 指针
      return Comp
    },      
    useState(initialValue) {
   
      hooks[currentHook] = hooks[currentHook] || initialValue
      const setStateHookIndex = currentHook
      // 这里我们暂且默认 setState 方式第一个参数不传 函数,直接传状态
      const setState = newState => (hooks[setStateHookIndex] = newState)
      return [hooks[currentHook++], setState]
    }
  }
})()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

因此当重新渲染 App 的时候,再次执行 useState 的时候传入的参数 kevin , 0 也就不会去使用,而是直接拿之前 hooks 存储好的值。

hooks 规则

官网 hoos 规则中明确的提出 hooks 不要再循环,条件或嵌套函数中使用。

为什么不可以?

我们来看下

下面这样一段代码。执行 useState 重新渲染,和初始化渲染 顺序不一样就会出现如下问题

如果了解了上面 useState 模拟写法的存储方式,那么这个问题的原因就迎刃而解了。

相关参考视频讲解:进入学习

useEffect 解析

useEffect 使用

初始化会 打印一次 ‘useEffect_execute’, 改变年龄重新render,会再打印, 改变名字重新 render, 不会打印。因为依赖数组里面就监听了 age 的值

import React, {
    useState, useEffect } from 'react';

  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/275125?site
推荐阅读
相关标签
  

闽ICP备14008679号