//数组
let [a, b, c] = [1, 2, 3];
console.log(a); // 输出 1
console.log(b); // 输出 2
console.log(c); // 输出 3
//对象
let obj = {name: "John", age: 30};
let {name, age} = obj;
console.log(name); // 输出 "John"
console.log(age); // 输出 30
useState 运用了 JS 的解构赋值的思想。
数组和对象解构赋值的区别是数组的元素是按次序排列的。
数组解构时的变量的取值由数组元素的位置决定,变量名可以任意命名。
对象的属性没有次序,解构时变量名必须与属性同名才能取到正确的值。
因此使用数组更灵活,可以任意命名 state 和修改 state 的方法名。所以,使用数组的原因是:useState 的内部把 state 声成一个数组,需要顺序一一对应。
function Com() {
const[num, setNum] = useState(0);
return {
<div className="num">
<p>{num}</p>
<p>
<button onClick={()=>setNum(num + 1)}> 增加 </button>
</p>
</div>
}
}
每次点击 button 时,num 就会增加 1,组件就会重新 Render。
自己实现 useState 代码:
let _state;//全局 _state 用来存储 state 的值,避免重新渲染时被 useState 重置为初始值。
const useState = initiaValue => {
_state = _state === undefined ? initiaValue : _state;
const setState = (newVal) => {
_state = newVal;
render();
}
return [_state, setState]
}
上面的方案用一个 useState 没问题,若一个组件有多个 useState,由于数据都放在 state 里,所以会冲突。
改进的地方:把 state 改为数组,如下代码:
_state=[0,0]
let _state=[]; // 全局_state用来存储state的值,避免重新渲染的时候被useState重置为初始值
let index=0
const useState = initialValue=>{
const currentIndex=index
_state[currentIndex]=_state[currentIndex]=== undefined ?initialValue:_state[currentIndex]
const setState=(newVal)=>{
_state[currentIndex]=newVal
render()
}
index+=1
return [_state[currentIndex],setState]
}
[state,setState]=useState(initialValue) //返回一个包含2个元素的数组:状态值和状态更新函数
#总结:
-
useState 的内部原理是把 state 声明成一个数组,需要顺序一一对应。
-
由于一个组件可以使用多个 useState,为了避免冲突并确保 state 的准确性,useState 要使用数组而不是对象。