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



目录
相关文章
|
Linux Docker 异构计算
ModelScope问题之下载了官方镜像 但是启动不了如何解决
ModelScope镜像是指用于在ModelScope平台上创建和管理的容器镜像,这些镜像包含用于模型训练和推理的环境和依赖;本合集将说明如何使用ModelScope镜像以及管理镜像的技巧和注意事项。
610 0
|
2月前
|
机器学习/深度学习 自然语言处理 搜索推荐
大模型应用:电商智能推荐:基于本地大模型的冷启动智能推荐系统实例.61
本文介绍基于Qwen1.5-1.8B-Chat轻量大模型的电商智能推荐系统,解决冷启动、模糊意图理解与可解释性差等痛点;通过语义特征增强、个性化意图解析及自然语言推荐理由生成,提升准确性与用户体验,代码开源、易于中小团队落地。
322 13
|
5月前
|
人工智能 自然语言处理 机器人
适合电商的智能客服系统推荐(2025年12月更新)
瓴羊Quick Service是阿里云旗下智能客服产品,深度整合电商交易链路,支持全渠道协同与大模型应用,具备高并发稳定性,助力中大型电商实现服务智能化与业务增长。
|
6月前
|
数据采集 存储 监控
爬虫数据增量更新:时间戳对比策略实战指南
在数据驱动时代,增量爬虫是高效采集的关键。本文详解以时间戳为核心的增量更新策略,涵盖GitHub、电商等实战场景,提供Python代码示例与避坑指南,助你精准抓取新增数据,提升效率并规避反爬风险。
458 2
|
存储 运维 监控
阿里云飞天洛神云网络子系统“齐天”:超大规模云网络智能运维的“定海神针”
阿里云飞天洛神云网络子系统“齐天”:超大规模云网络智能运维的“定海神针”
612 3
|
XML JSON API
亚马逊商品详情 API 接口开发指南
亚马逊商品详情API为开发者、分析师及电商从业者提供了获取商品数据的便捷途径。通过HTTP/HTTPS协议,支持GET/POST请求,可指定市场代码(如US、UK)和其他参数(如数据格式、附加信息)。返回信息涵盖商品基本信息(标题、品牌等)、价格(售价、货币单位)、库存状态、评论与评分(平均分、总评论数)以及销售排名等,助力市场分析、竞品研究和业务优化。
363 22
|
自然语言处理 API 开发者
强强联合,开源中文DeepSeek-R1蒸馏数据集联合魔搭社区,一起来训练中文版推理模型!
近期,刘聪NLP开源了开源中文DeepSeek-R1(满血)蒸馏数据集包括SFT版本和普通版本,话不多说,先放数据下载链接。
762 1
|
小程序
微信小程序App()方法与getApp()方法
微信小程序App()方法与getApp()方法
1069 0
微信小程序App()方法与getApp()方法
|
监控 网络协议 算法
OSPFv2与OSPFv3的区别:全面解析与应用场景
OSPFv2与OSPFv3的区别:全面解析与应用场景
719 0
|
机器学习/深度学习 数据可视化 TensorFlow
使用卷积神经网络构建一个图像分类模型
使用卷积神经网络构建一个图像分类模型
412 0

热门文章

最新文章