在使用ReactJS Functional Component的Hooks中,我想调用一个函数,该函数将:
Timeout
以在固定的时间内再次调用自身这是该组件的简化示例:
const Counter = () => {
const [count, setCount] = useState(0);
const [counterTimeout, setCounterTimeout] = useState(null);
const updateCount = () => {
setCount(count + 1);
console.log(count);
setCounterTimeout(window.setTimeout(updateCount, 500));
};
useEffect(() => {
updateCount();
return window.clearTimeout(counterTimeout);
}, []);
return null;
};
我正在苦苦挣扎的是为什么不更新State属性?
此外,加分,如果您可以告诉我如何清除组件卸载中的Timeout
(肯定不会那样做);
谢谢❤️
答案 0 :(得分:0)
这应该有效:
const Counter = () => {
const [count, setCount] = useState(0);
const updateCount = () => {
setCount(count + 1);
};
useEffect(() => {
const interval = setInterval(updateCount, 1000);
return () => {
clearInterval(interval);
};
}, [count]);
return <span>{count}</span>;
};
https://codesandbox.io/s/react-hooks-counter-demo-520gr
使用setTimeout。
const Counter = () => {
const [count, setCount] = useState(0);
const updateCount = () => {
setCount(count + 1);
};
useEffect(() => {
const timeout = setTimeout(updateCount, 1000);
return () => {
clearTimeout(timeout);
};
}, [count]);
return <span>{count}</span>;
};
答案 1 :(得分:-1)
我已经修复了您的代码,并会尝试解释,希望是正确的。我还添加了使用setInterval
的替代方法,而不是重新触发setTimeout
。
https://codesandbox.io/s/serene-ives-502hz
问题是组件的重新呈现。每次更改属性或状态对象时,都会重新渲染组件,以便再次创建其中的所有对象。 updateCount
也是如此。但是useEffect
内部的方法仅在其中一个监听参数发生更改时才会重新创建。在您的情况下,该数组为空,因此在安装Counter
组件时,它将仅运行一次。因此,由于updateCount
,对setCount
的引用与重新渲染后在组件内部的引用不同。
要绕过此问题,useRef
可以解决。这样可以创建一个“静态”变量。因此,在重新渲染组件时将不会重新创建它。因此,我们可以在此处保留对计时器处理程序的引用,然后调用clearTimeout
。接下来是对count
的访问。
我不确定此解释是否正确:setCount
将不会更新当前的count
,而是会创建一个新对象。因此,在调用setCount
之后,当前count
仍具有相同的旧值。为此,setCount
可以通过提供将在内部使用count
当前值进行调用的函数以不同的方式调用。要输出console.log
,只需添加另一个useEffect
,每次count
更改时就会通过监听count
来调用。
const Counter = () => {
const [count, setCount] = useState(0);
const counterTimeout = useRef(null);
const updateCount = () => {
setCount(count => count + 1);
counterTimeout.current = window.setTimeout(updateCount, 500);
};
useEffect(() => {
console.log("count", count);
}, [count]);
useEffect(() => {
updateCount();
return () => {
window.clearTimeout(counterTimeout.current);
};
}, []);
return null;
};
为完成此操作,我可以使用相同的方法,但是使用setInterval
。因此,间隔处理仅在useEffect
内部,因此不需要引用。通过将useCallback
用于updateCount
,它也有一个小的优化。
const CounterInterval = () => {
const [count, setCount] = useState(0);
const updateCount = useCallback(() => {
setCount(count => count + 1);
}, [setCount]);
useEffect(() => {
console.log("interval count", count);
}, [count]);
useEffect(() => {
const counterTimeout = window.setInterval(updateCount, 500);
return () => {
window.clearInterval(counterTimeout);
};
}, []);
return null;
};