Reactjs 如何处理useEffect闭包中的过时状态值?
下面的示例是一个计时器组件,它有一个按钮(用于启动计时器)和两个标记,显示经过的秒数和经过的秒数乘以2 但是,它不起作用( 代码Reactjs 如何处理useEffect闭包中的过时状态值?,reactjs,react-hooks,Reactjs,React Hooks,下面的示例是一个计时器组件,它有一个按钮(用于启动计时器)和两个标记,显示经过的秒数和经过的秒数乘以2 但是,它不起作用( 代码 import React, { useState, useEffect } from "react"; const Timer = () => { const [doubleSeconds, setDoubleSeconds] = useState(0); const [seconds, setSeconds] = useState
import React, { useState, useEffect } from "react";
const Timer = () => {
const [doubleSeconds, setDoubleSeconds] = useState(0);
const [seconds, setSeconds] = useState(0);
const [isActive, setIsActive] = useState(false);
useEffect(() => {
let interval = null;
if (isActive) {
interval = setInterval(() => {
console.log("Creating Interval");
setSeconds((prev) => prev + 1);
setDoubleSeconds(seconds * 2);
}, 1000);
} else {
clearInterval(interval);
}
return () => {
console.log("Destroying Interval");
clearInterval(interval);
};
}, [isActive]);
return (
<div className="app">
<button onClick={() => setIsActive((prev) => !prev)} type="button">
{isActive ? "Pause Timer" : "Play Timer"}
</button>
<h3>Seconds: {seconds}</h3>
<h3>Seconds x2: {doubleSeconds}</h3>
</div>
);
};
export { Timer as default };
过时值的问题仍然存在()
问题
那么,对于这个场景的建议是什么呢?我是否接受性能影响并简单地将“秒”添加到依赖项数组中?我是否创建另一个依赖于“秒”的useEffect块并在其中调用“setDoubleSeconds()”?我是否将“秒”和“doubleSeconds”合并到单个状态对象中?我是否使用引用
此外,您可能会想,“为什么不简单地将Seconds x2:{doubleSeconds}
”更改为Seconds x2:{Seconds*2}
,并删除“doubleSeconds”状态?“。在我的实际应用程序中,doubleSeconds被传递给子组件,我不希望子组件知道秒如何映射到doubleSeconds,因为这会降低子组件的可重用性
谢谢
- 我是否接受了性能上的打击,并简单地向依赖项数组添加“秒”
- 我是否创建另一个依赖于“秒”的useEffect块并在其中调用“setDoubleSeconds()”
- 我是否将“秒”和“双秒”合并到单个状态对象中
- 我使用refs吗
useffect(()=>{
设置双秒(秒*2);
},[秒];
然而:
在我的实际应用程序中,doubleSeconds被传递给子组件,我不希望子组件知道如何将seconds映射到doubleSeconds,因为这会降低子组件的可重用性
这是有问题的。子组件的实现方式可能如下所示:
constchild=({second})=>(
秒:{second}s
);
和父组件应如下所示:
const[seconds,setSeconds]=useState(0);
useffect(()=>{
//换秒
}, []);
返回(
);
这将是一种更加清晰和简洁的方式
- 我是否接受了性能上的打击,并简单地向依赖项数组添加“秒”
- 我是否创建另一个依赖于“秒”的useEffect块并在其中调用“setDoubleSeconds()”
- 我是否将“秒”和“双秒”合并到单个状态对象中
- 我使用refs吗
useffect(()=>{
设置双秒(秒*2);
},[秒];
然而:
在我的实际应用程序中,doubleSeconds被传递给子组件,我不希望子组件知道如何将seconds映射到doubleSeconds,因为这会降低子组件的可重用性
这是有问题的。子组件的实现方式可能如下所示:
constchild=({second})=>(
秒:{second}s
);
和父组件应如下所示:
const[seconds,setSeconds]=useState(0);
useffect(()=>{
//换秒
}, []);
返回(
);
这将是一种更加清晰和简洁的方法。您可以通过几种方式访问effect回调中的值,而无需将其添加为dep
设置状态
。您可以通过状态变量的设置器点击状态变量的最新值secondsRef.current
访问代码块中的seconds
,而无需触发deps更改
setDoubleSeconds(secondsRef.current * 2);
在我看来,您永远不应该从deps数组中忽略依赖项。如果您需要deps不更改,请使用如上所述的方法确保您的值是最新的
总是首先考虑是否有更优雅的方式编写代码,而不是将值放入回调中。在示例中,代码> DouBuffEnss/Cuth>可以表示为<代码>秒< /代码>。< /P>
const [seconds, setSeconds] = useState(0);
const doubleSeconds = seconds * 2;
有时应用程序并不是那么简单,所以您可能需要使用上面描述的hack。您可以通过几种方式访问effect回调中的值,而无需将其添加为dep
设置状态
。您可以通过状态变量的设置器点击状态变量的最新值secondsRef.current
访问代码块中的seconds
,而无需触发deps更改
setDoubleSeconds(secondsRef.current * 2);
在我看来,您永远不应该从deps数组中忽略依赖项。如果您需要deps不更改,请使用如上所述的方法确保您的值是最新的
总是首先考虑是否有更优雅的方式编写代码,而不是将值放入回调中。在示例中,代码> DouBuffEnss/Cuth>可以表示为<代码>秒< /代码>。< /P>
const [seconds, setSeconds] = useState(0);
const doubleSeconds = seconds * 2;
有时应用程序并不是那么简单,所以您可能需要使用上面描述的hack
const [seconds, setSeconds] = useState(0);
const doubleSeconds = seconds * 2;