[英]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.