【发布时间】:2021-01-15 04:53:14
【问题描述】:
我刚刚尝试了 react 功能组件,它似乎很神奇。在我的组件函数中,我都初始化我的状态并返回我的视图。视图中的动作可以调用组件函数范围内定义的函数,从而更新状态。
我的假设是函数组件的函数只被调用一次,但惊讶地发现每次发生状态变化时都会调用它。如果此函数初始化状态,并且在每次状态更改时都被调用,那么我的状态如何不会在每次状态更改时重置?
这是一个键盘记录器组件,它从输入中获取击键并将它们显示在 div 中:
export const KeyLogger = () => {
const [keysLogged, setKeysLogged] = React.useState<string[]>([]);
const logKey = (key: string) => {
setKeysLogged(keysLogged.concat(key));
}
console.log("HERE");
return (
<React.Fragment>
<input onKeyUp={ev => logKey(ev.key)}/>
<br/>
<div>{keysLogged}</div>
</React.Fragment>
);
};
当我使用这个组件时,我看到keysLogged 会随着我的输入而增长。
我还看到每次击键都会记录“HERE”。
当我的功能组件的第一行似乎每次调用都初始化keysLogged 时,这怎么可能?
const [keysLogged, setKeysLogged] = React.useState<string[]>([]);
编辑:
使用@Ethan Lipkind 的回复我发现:
每个组件都有一个内部“记忆单元”列表。它们只是 JavaScript 对象,我们可以在其中放置一些数据。当你调用 useState() 之类的 Hook 时,它会读取当前单元格(或在第一次渲染期间对其进行初始化),然后将指针移动到下一个单元格。这就是多个 useState() 调用各自获取独立本地状态的方式。
所以 react 知道根据 useState 被调用的顺序使用哪个值。而且因为它使用的是useState 而不是createState,所以如果内存单元位置的值已经存在,react 知道不会重新初始化值。
当我在每次调用中切换 keysLoggedA 和 keysLoggedB 的初始化顺序时,这会产生有趣的影响。
let counter = 0;
export const KeyLogger = () => {
counter++;
let keysLoggedA: any;
let setKeysLoggedA: any;
let keysLoggedB: any;
let setKeysLoggedB: any;
if (counter % 2 === 0) {
[keysLoggedA, setKeysLoggedA] = React.useState<string[]>([]);
[keysLoggedB, setKeysLoggedB] = React.useState<string[]>([]);
} else {
[keysLoggedB, setKeysLoggedB] = React.useState<string[]>([]);
[keysLoggedA, setKeysLoggedA] = React.useState<string[]>([]);
}
const logKey = (key: string) => {
setKeysLoggedA(keysLoggedA.concat(key));
}
console.log("HERE");
return (
<React.Fragment>
<input onKeyUp={ev => logKey(ev.key)}/>
<br/>
<div>{keysLoggedA}</div>
<div>{keysLoggedB}</div>
</React.Fragment>
);
};
即使我只打电话给setKeysLoggedA,你也可以看到keysLoggedA 和keysLoggedB 都得到了更新。
这是因为它完全依赖于 order useState 被调用。这是有道理的,我不知道它还能是什么,但很高兴知道魔法是如何运作的。
【问题讨论】:
标签: javascript reactjs