【问题标题】: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 知道不会重新初始化值。

当我在每次调用中切换 keysLoggedAkeysLoggedB 的初始化顺序时,这会产生有趣的影响。

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,你也可以看到keysLoggedAkeysLoggedB 都得到了更新。

这是因为它完全依赖于 order useState 被调用。这是有道理的,我不知道它还能是什么,但很高兴知道魔法是如何运作的。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    每次状态更改时,都会触发重新渲染,这就是您在每次击键时看到日志的原因。由于 useState 钩子在后台工作的方式,不会在每个函数调用上重新初始化状态:https://reactjs.org/docs/hooks-state.html

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-21
    • 2018-10-19
    • 2020-04-03
    • 2020-12-26
    • 2020-10-18
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多