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,并触发更新



目录
相关文章
|
10月前
|
前端开发 JavaScript 安全
useEffect 与 useLayoutEffect区别
useEffect 与 useLayoutEffect区别
59 0
|
2月前
|
前端开发 JavaScript 数据格式
react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )
react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )
56 1
|
3月前
|
前端开发
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
|
4月前
|
前端开发 JavaScript
React中的状态管理:useState与useReducer的使用与探讨
【4月更文挑战第25天】本文探讨了React中构建动态界面的关键——状态管理,重点关注`useState`和`useReducer` Hook。`useState`适用于简单状态管理,例如计数器,而`useReducer`在处理复杂逻辑和多个状态更新时更具优势,提供更好的组织和可维护性。选择使用哪个取决于状态逻辑复杂度、可维护性和性能需求。合理运用这两个工具能实现高效、可维护的React应用。
|
4月前
|
存储 前端开发 JavaScript
React Hooks实战:从useState到useContext深度解析
React Hooks 深度解析:useState用于函数组件的状态管理,通过初始化和更新状态实现渲染控制;useContext则提供跨组件数据传递。useState的状态更新是异步的,不支持浅比较,可结合useEffect处理副作用。useContext在多层组件间共享状态,但可能导致不必要的渲染。两者结合可创建复杂应用场景,如带主题切换的计数器。了解其工作原理和优化策略,能有效提升React应用性能。
73 0
|
JavaScript
useEffect和useLayoutEffect有什么区别
useEffect和useLayoutEffect有什么区别
|
4月前
|
前端开发
说说React中setState和replaceState的区别?
在 React 中,setState()和 replaceState()是用于更新组件状态的两个方法。它们之间有一些区别
37 0
|
9月前
|
存储 前端开发 JavaScript
useRef 和 useState 哪个更好?
useRef 和 useState 哪个更好?
80 1
|
4月前
|
前端开发 JavaScript
useState和useReducer的区别?
useState和useReducer的区别?
62 0
|
4月前
|
缓存 前端开发 JavaScript
React.Memo和useMemo的区别?
React.Memo和useMemo的区别?
147 0