[英]Reactjs - SetTimeout with state change re-render
我目前在开发 Typescript React App 时遇到了一些问题。 下面是我当前的代码..
但它的行为不像我想要的那样。 :)
所以我想要实现的是,每当加载组件时,带有 getData(depth) 的数据就会运行一次,之后每 5 秒运行一次。
但是当 Depth 随 Dropdown.item 按钮发生变化时,它应该重新渲染,并且 getData() 应该使用我们刚刚在 state 中设置的新深度值运行。然后继续使用新值渲染。 .
我一直在努力解决这个问题,所以非常感谢任何帮助!
谢谢!
import React, { useState, useEffect } from "react";
const chart = () => {
const [depth, setDepth] = useState(20);
const [chartData, setChartData] = useState({})
//Getting the data when the app initially renders and should keep rendering every 5 seconds after that.
//When the value of the depth changes, we should stop getting the data with the old depth //value and should start a new interval of 5 seconds and just keep running with the new //depth value
//When first entering the app, this should run immediately with the initial depth state //(20)
useEffect(() => {
const interval = setInterval(() => {
//this code is not the actual code, just an example of what is running
const data = getData(depth)
//just fetched the new data, now setting it..
setChartData(data)
}, 5000);
return () => clearInterval(interval);
}, []);
return (
<div>
<div>
<DropdownButton id="dropdown-basic-button" title="Depth Percentage">
<Dropdown.Item onClick={() => setDepth(5)}>5%</Dropdown.Item>
<Dropdown.Item onClick={() => setDepth(20)}>20%</Dropdown.Item>
</DropdownButton>
</div>
<div>
//Rendering the Chart here....
</div>
</div>
);
};
export default chart;
这是因为useEffect
钩子需要第二个参数,称为dependency array
,其中这个依赖数组对于内部回调(inisde useEffect)访问你想要的最新值很重要。
所以你在这里并不完全真实,如果内部回调取决于depth
以使其最新更新,那么你应该将它包含在依赖数组中
useEffect(() => { ... }, [ depth ]);
这是针对depth
的,但是编写此代码会立即导致问题,因为对于每个新的depth
值,内部回调将被调用,并且setInterval
将再次重新运行(导致许多...许多间隔)。
要解决这个问题,您应该避免在基于hooks
的代码中一起使用setInterval
allll。
如果间隔真的很重要,我有一个建议给你
const [intervalCount, setIntervalCount] = useState(0);
const [depth, setDepth] = useState(20);
const [chartData, setChartData] = useState({})
useEffect(() => {
// when depth change re-fetch data and set it
const data: any = getData(depth);
setChartData(data);
}, [depth])
// simulate set interval behavior
// each 5 s this function will be re-invoked
useEffect(() => {
// re-fetch data and set it
const data: any = getData(depth);
setChartData(data);
// wait 5 s before cause a re-render
setTimeout(() => {
setIntervalCount(count => count + 1);
}, 5000);
}, [intervalCount]);
更新:Dan Abramov 博客评分后
您可以找到使用setInterval
和hooks
的更好的优雅解决方案
他制作了一个名为useInterval
的自定义钩子
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
用法就像
useInterval(() => {
// Your custom logic here
setCount(count + 1);
}, 1000);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.