功能性反应如何不重置状态?
Posted
技术标签:
【中文标题】功能性反应如何不重置状态?【英文标题】:How does Functional React Not Reset State? 【发布时间】: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 被调用。这是有道理的,我不知道它还能是什么,但很高兴知道魔法是如何运作的。
【问题讨论】:
【参考方案1】:每次状态更改时,都会触发重新渲染,这就是您在每次击键时看到日志的原因。由于 useState
钩子在后台工作的方式,不会在每个函数调用上重新初始化状态:https://reactjs.org/docs/hooks-state.html
【讨论】:
对于那些希望在传递的“初始值”更改时重置状态的人,请参阅this thread 和use-state-with-deps package。以上是关于功能性反应如何不重置状态?的主要内容,如果未能解决你的问题,请参考以下文章
在 ClearTextOnFocus 之后反应原生重置 TextInput