useState原理

简介: 每个函数组件对应一个React节点每个节点保存着state和index (这个state可能描述不准确,但主要是让大家想清楚这个事情,应该是一个类似state的东西)useState会读取state[index]index由useState出现的顺序决定setState会修改State,并触发更新

useState用法

脑补一下点击button后会发生什么

function App() {
  const [n, setN] = React.useState(0);
  return (
    <div className="App">
      <p>{n}</p>
      <p>
        <button onClick={() => setN(n + 1)}>+1</button>
      </p>
    </div>
  );
}

会使页面上的n变量由0变成1

71604b3e9f920719707d9a6efc82bc1.png

脑补之后

问自己几个问题

执行setN的时候会发生什么?n会变吗?App()会重新执行吗?

如果App()会重新执行,那么useState(0)的时候,n每次的值会有不同吗?

通过console.log你就能得到答案

分析

setN

setN一定会修改数据x,(我们暂且将这个不知道的东西称为x),将n+1存入x

setN一定会触发<App/>重新渲染(render)

useState

useState肯定会从x读取到n的最新值

x

每个组件有自己的数据x,我们将其命名为state

尝试实现React.useState

function myUseState(initialValue) {
  var state = initialValue;
  function setState(newState) {
    state = newState;
    render();
  }
  return [state, setState];
}
// render方法我们就不实现了,直接让它渲染
const render = () => ReactDOM.render(<App />, rootElement);
function App() {
  const [n, setN] = myUseState(0);
  return (
    <div className="App">
      <p>{n}</p>
      <p>
        <button onClick={() => setN(n + 1)}>+1</button>
      </p>
    </div>
  );
}

完全没有变化啊

因为myUseState会将state重置

我们需要一个不会被myUseState重置的变量

那么这个变量只要声明在myUseState外面即可

// ***********************************
let _state;
// ***********************************
function myUseState(initialValue) {
  _state = _state === undefined ? initialValue : _state;
  function setState(newState) {
    _state = newState;
    render();
  }
  return [_state, setState];
}
const render = () => ReactDOM.render(<App />, rootElement);
function App() {
  const [n, setN] = myUseState(0);
  return (
    <div className="App">
      <p>{n}</p>
      <p>
        <button onClick={() => setN(n + 1)}>+1</button>
      </p>
    </div>
  );
}

useState就这么简单?

别急,还有问题

如果一个组件用了两个useState怎么办?

由于所有数据都方在_state,所以会冲突

改进思路

把_state做成一个对象

比如_state = { n:0, m:0}

不行,因为useState(0)并不知道变量叫n还是m

把_state做成数组

比如_state= [ 0, 0 ]

貌似可行,我们来试试看

多个useState

// ***********************************
let _state = [];
let index = 0;
// ***********************************
function myUseState(initialValue) {
  const currentIndex = index;
  index += 1;
  _state[currentIndex] = _state[currentIndex] || initialValue;
  const setState = newState => {
    _state[currentIndex] = newState;
    render();
  };
  return [_state[currentIndex], setState];
}
const render = () => {
  index = 0;
  ReactDOM.render(<App />, rootElement);
};
function App() {
  const [n, setN] = myUseState(0);
  const [m, setM] = myUseState(0);
  console.log(_state);
  return (
    <div className="App">
      <p>{n}</p>
      <p>
        <button onClick={() => setN(n + 1)}>+1</button>
      </p>
      <p>{m}</p>
      <p>
        <button onClick={() => setM(m + 1)}>+1</button>
      </p>
    </div>
  );
}

_state数组方案缺点

useState调用顺序

如果第一次渲染时,n是第一个,m是第二个,k是第三个

则第二次渲染时必须保证顺序完全一致

所以React不允许出现如下代码

2 ReactDOM . render (< cApp />, rootElement ):
25
 Function App (){
 const [ n , setN ] React . useState (0); let m , setM ;
 if ( n %2-1)
[ m , setM ]= React . useState (0): return (
 cdiv className -" App ">< p > fnj </ p >
< button onC1ick={()=> setN ( n .1))>+1</ button >
Console wos cleored 
 Uncaught Invariant Violation : Rendered more hooks than during the previous render .
 invariant (https://j6y72.csb.anp/no
 odules / react - dom / cjs / react - dom . develonment . js :55:15)
 updateworkinProgressHook (httR5i/Z1by72.csb. anp / node moduies / react - gon /c3sreact- gom . oeveopn 
 updateReducer (https://16y72.csb.app/nodem
modu1es/ react - dom /c1s/ react - dom .deye1ooment.1s1139991
 nt .1s:13294:10)

总结

  1. 每个函数组件对应一个React节点
  2. 每个节点保存着stateindex (这个state可能描述不准确,但主要是让大家想清楚这个事情,应该是一个类似state的东西)
  3. useState会读取state[index]
  4. indexuseState出现的顺序决定
  5. setState会修改State,并触发更新



目录
相关文章
|
数据采集 机器学习/深度学习 数据挖掘
python数据分析——数据预处理
数据预处理是数据分析过程中不可或缺的一环,它的目的是为了使原始数据更加规整、清晰,以便于后续的数据分析和建模工作。在Python数据分析中,数据预处理通常包括数据清洗、数据转换和数据特征工程等步骤。
397 0
|
存储 编解码 并行计算
【软件设计师备考 专题 】计算机系统的组成、体系结构分类及特性
【软件设计师备考 专题 】计算机系统的组成、体系结构分类及特性
252 0
|
12月前
|
前端开发 JavaScript
深入理解并实践React Hooks —— useEffect与useState
深入理解并实践React Hooks —— useEffect与useState
305 1
|
算法 前端开发 JavaScript
React的diff算法原理
React的diff算法原理
225 0
|
JSON 缓存 前端开发
【React】React原理面试题集锦
本文集合一些React的原理面试题,方便读者以后面试查漏补缺。作者给出自认为可以让面试官满意的简易答案,如果想要了解更深刻,可以点击链接查看对应的详细博文。在此对链接中的博文作者非常感谢🙏。
272 0
|
JavaScript 前端开发 算法
React技术栈-虚拟DOM和DOM diff算法
这篇文章介绍了React技术栈中的虚拟DOM和DOM diff算法,并通过一个实际案例展示了如何使用React组件和状态管理来实现动态更新UI。
115 2
|
11月前
|
SQL 存储 关系型数据库
MySQL能否查询某张表的操作记录
MySQL能否查询某张表的操作记录
1759 1
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
|
设计模式 开发框架 前端开发
实践总结|前端架构设计的一点考究(下)
作者将【DDD、六边形、洋葱、清洁、CQRS】进行深入学习并梳理总结的一个前端架构设计,并且经历一定应用实践的考验。
361 0
|
缓存 前端开发 JavaScript
React 面试题2
React 面试题2
188 0