从原理上解读useState钩子函数

简介: 从原理上解读useState钩子函数

原生useState具有的几个特点

  1. 返回一个数组,数组的第一个参数值是状态值,第二个参数值是设置状态的方法。
  2. useState会判断传入的state是初始值还是已存在的值。
  3. useState可能被多次调用
  4. 调用设置状态的方法后需要重新渲染组件。

手写useState

第一步:用不同的数组来分别存放状态值和设置状态的方法

let states = [];
let setters = [];
let stateId = 0;
复制代码

第二步:判断useState传入的初始状态值是否已经存在

存在用以前的,不存在则使用初始状态值

states[stateId] = states[stateId] ? states[stateId] : initialState;
复制代码

第三步:通过状态的id来返回设置状态的方法,然后加入到设置方法的数组中

注意:自定义的渲染函数必须能够操作全局的状态id.

setters.push(createSetter(stateId));
function createSetter(stateId) {
    return function (newState) {
        states[stateId] = newState;
        myRender();
    }
}
function myRender() {
    stateId = 0;
    ReactDOM.render(<App />, document.querySelector('#root'));
}
复制代码

第四步:返回第i个状态值和操作状态的方法,并对stateId+1

let value = states[stateId];
let setter = setters[stateId];
stateId++;
return [value, setter]
复制代码

完整代码

import React from 'react'
import ReactDOM from 'react-dom'
// 自定义Hook
/**
 * @description: 手写useState
 * @param {*}
 * @return {*}
 */
let states = [];
let setters = [];
let stateId = 0;
function createSetter(stateId) {
    return function (newState) {
        states[stateId] = newState;
        myRender();
    }
}
function myRender() {
    stateId = 0;
    ReactDOM.render(<App />, document.querySelector('#root'));
}
function myUseState(initialState) {
    // 判断state是否存在,存在则使用以前的,不存在则使用初始值
    states[stateId] = states[stateId] ? states[stateId] : initialState;
    setters.push(createSetter(stateId));
    let value = states[stateId];
    let setter = setters[stateId];
    stateId++;
    return [value, setter]
}
function App() {
    const [count, setCount] = myUseState(0);
    const [name, setName] = myUseState('张三');
    return (
        <div>
            <h1>当前求和为:{count}</h1>
            <button onClick={() => setCount(count + 1)}>点我+1</button>
            <h1>当前姓名为:{name}</h1>
            <button onClick={() => setName('李四')}>点我切换姓名</button>
        </div>
    )
}
ReactDOM.render(<App />, document.querySelector('#root'));
复制代码

CodeSandBox在线实现地址

参考资料

目录
打赏
0
0
0
0
6
分享
相关文章
精选11款炫酷的前端动画特效分享(附在线演示)
分享11款非常不错炫酷的前端特效源码 其中包含css动画特效、js原生特效、svg特效等 下面我会给出特效样式图或演示效果图 但你也可以点击在线预览查看源码的最终展示效果及下载源码资源
三大行业案例:AI大模型+Agent实践全景
本文将从AI Agent和大模型的发展背景切入,结合51Talk、哈啰出行以及B站三个各具特色的行业案例,带你一窥事件驱动架构、RAG技术、人机协作流程,以及一整套行之有效的实操方法。具体包含内容有:51Talk如何让智能客服“主动进攻”,带来约课率、出席率双提升;哈啰出行如何由Copilot模式升级为Agent模式,并应用到客服、营销策略生成等多个业务场景;B站又是如何借力大模型与RAG方法,引爆了平台的高效内容检索和强互动用户体验。
1663 5
解决ERROR in Conflict: Multiple assets emit different content to the same filename index.html 的问题
解决ERROR in Conflict: Multiple assets emit different content to the same filename index.html 的问题
1056 1
plant simulation物流系统仿真案例
plant simulation物流系统仿真案例
432 0
java中强大的时间处理工具:Calendar类(日历类)
`Calendar`类是Java中用来处理日期和时间的类,提供了许多属性来获取日期和时间的不同部分,如年、月、日、小时等。`Calendar`的常用属性包括`YEAR`(年)、`MONTH`(月)、`DATE`/`DAY_OF_MONTH`(日)、`DAY_OF_YEAR`(一年中的第几天)、`DAY_OF_WEEK_IN_MONTH`(一月中第几个星期)、`DAY_OF_WEEK`/`WEEK_OF_MONTH`(星期)等。
180 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等