原生useState具有的几个特点
- 返回一个数组,数组的第一个参数值是状态值,第二个参数值是设置状态的方法。
- useState会判断传入的state是初始值还是已存在的值。
- useState可能被多次调用
- 调用设置状态的方法后需要重新渲染组件。
手写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'));