gpt4 book ai didi

javascript - 在 state 和 ref 中保持相同的值是 React 中的常见做法吗?

转载 作者:行者123 更新时间:2023-12-05 08:04:18 24 4
gpt4 key购买 nike

我的 React 应用程序使用 setTimeout()setInterval()。在它们内部,我需要访问状态值。正如我们所知,闭包一旦创建就绑定(bind)到它们的上下文,因此在 setTimeout()/setInterval() 中使用状态值不会使用最新值。

为了简单起见,假设我的组件是这样定义的:

import { useState, useEffect, useRef } from 'react';

const Foo = () => {
const [number, setNumber] = useState(0);
const numberRef = useRef(number);

// Is this common? Any pitfalls? Can it be done better?
numberRef.current = number;

useEffect(
() => setInterval(
() => {
if (numberRef.current % 2 === 0) {
console.log('Yay!');
}
},
1000
),
[]
);

return (
<>
<button type="button" onClick={() => setNumber(n => n + 1)}>
Add one
</button>
<div>Number: {number}</div>
</>
);
};

我总共想出了 3 个想法来实现这一目标,其中任何一个是公认的模式吗?

  1. 在每次渲染时将状态值分配给 ref,就像上面一样:

    numberRef.current = number;

    好处是代码非常简单。

  2. 使用 useEffect() 注册 number 的变化:

    useEffect(
    () => numberRef.current = number,
    [number]
    );

    这个看起来更像 React,但真的有必要吗?当可以使用第 1 点的简单赋值时,它实际上不会降低性能吗?

  3. 使用自定义 setter :

    const [number, setNumberState] = useState(0);
    const numberRef = useRef(number);

    const setNumber = value => {
    setNumberState(value);
    numberRef.current = value;
    };

在 state 和 ref 中具有相同的值是 React 的常见模式吗?这 3 种方式中的任何一种是否出于某种原因比其他方式更受欢迎?有哪些替代方案?

最佳答案

2021-10-17 编辑:

因为这看起来很常见,所以我想将整个逻辑包装成一个直观的

useInterval(
() => console.log(`latest number value is: ${number}`),
1000
)

其中 useInterval 参数始终可以“访问”最新状态。

CodeSandbox 中玩了一会儿之后,我意识到没有其他人没有考虑过解决方案。

你瞧,Dan Abramov 本人发表了一篇博文,为我们的问题提供了精确的解决方案 https://overreacted.io/making-setinterval-declarative-with-react-hooks/

我强烈建议阅读完整的博客,因为它描述了声明式 React 编程和命令式 API 之间不匹配的普遍问题。 Dan 还解释了他(逐步)开发完整解决方案的过程,该解决方案能够在需要时更改间隔延迟。

Here (CodeSandbox)你可以在你的特定情况下测试它。


原始答案:

1.

numberRef.current = number;

我会避免这种情况,因为我们通常希望在 useEffect 而不是 render 方法中进行状态/引用更新。

在这种特殊情况下,它没有太大影响,但是,如果您要添加另一个状态并对其进行修改 -> 将触发渲染周期 -> 这段代码也会运行并无缘无故地分配一个值(数字值不会改变)。

2.

useEffect(
() => numberRef.current = number,
[number]
);

恕我直言,这是您提供的所有 3 种方式中最好的方式。这是一种将托管状态“同步”到可变 ref 对象的干净/声明方式。

3.

const [number, setNumberState] = useState(0);
const numberRef = useRef(number);

const setNumber = value => {
setNumberState(value);
numberRef.current = value;
};

在我看来,这并不理想。其他开发人员习惯于 React API,可能看不到您的自定义 setter,而是在添加更多逻辑时使用默认的 setNumberState,期望它被用作“真实来源”-> setInterval 不会得到最新数据。

关于javascript - 在 state 和 ref 中保持相同的值是 React 中的常见做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69483390/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com