引入
当你看到这样一串代码,你是怎么想的?
function App() {
const [n, setN] = React.useState(0);
return (
<div className="App">
<p>{n}</p>
<button onClick={() => setN(n + 1)}>+1</button>
</div>
);
}
ReactDOM.render(<App />, rootElement);
我来猜一猜:
- 用useState声明了一个n,一个改变n值的方法setN,让n初始值为0
- 调用setN之后n的值会发生改变
但过程真的是这样的吗?
console.log
- 在App组件内加一句console.log('App');
你会发现App在每一次点击button,都进行了刷新
每次setN都重新进行了render - 在App组件内加一句console.log(n)
你会发现每次点击button,打出的n都是不同的,第一次是0,第二次是1,第三次是2 ...
useState(0)中的0只在第一次初始化生效(否则每一次执行n都是0)
雏形
function myUseState(initialValue) {
var state = initialValue;
function setState(newState) {
state = newState;
render();
}
return [state, setState];
}
const render = () => ReactDOM.render(<App />, rootElement);
点击后发现了什么呢? n的值并没有改变。
因为每一次myUseState都把n初始化成了0
改良
let myState
function myUseState(initialValue) {
var myState = myState===undefined? initialValue : myState; //控制初始化
function setState(newState) {
myState = newState;
render();
}
return [myState, setState];
}
const render = () => ReactDOM.render(<App />, rootElement);
- 经过改造,myUseState终于正常运行了
- 你也可以看到,setN根本没有改变n,它改变了一个myState的值,保存在其他地方
- 在调用setN的时候,实际上是把myState的值赋给n,并且重新进行了rerender,才给你造成了setN改变了n的错觉
我用了好多个useState咋办?
方案 1 : 把myState做成对象 {n:0, m:1}
- useState()只能传一个参数,没法区分键名n和m
方案 2 : 把myState做成数组 [0, 1]
- 可行(就是这种思路实现的)
但是!方案 2 会区分顺序!!
所以还需要index来辅助记录顺序
这也就导致了我们在使用useState的时候必须写在顶层,不能放在判断语句中,否则就会打乱数组的顺序造成错误。
我在好多个组件都用了useState咋办?
方案1:放在全局变量里
- 只有智障才会放在全局变量里
方案2:放在虚拟React节点中
- 虚拟react节点的数据类型是对象,正好可以在每一个组件的节点上加上 myState 和 index 的键值对!完美解决
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。