![](/img/trans.png)
[英]Updated state value is not reflected inside setInterval() in React
[英]SetInterval is not showing updated state
在調用setInterval
函數之前,我已將狀態設置為true。 但是,即使用狀態的新值觸發了useEffect
鈎子,也沒有反映在setInterval
函數中。
此處的代碼沙箱: https : //jsfiddle.net/6e05tc2L/3/
let interval;
const Component = () => {
React.useEffect(() => {
console.log('State updated to', state);
});
const [state, setState] = React.useState(false);
const on = () => {
setState(true);
interval = setInterval(() => {
console.log(state);
}, 1000);
}
const off = () => {
setState(false);
clearInterval(interval);
}
const toggle = () => state ? off() : on()
return (<div>
<button onClick={toggle}>Toggle State</button>
</div>);
}
ReactDOM.render(
<Component />,
document.getElementById('container')
);
一旦更新,它不應該使用狀態的新值嗎?
傳遞給useEffect的函數內部的值在每個渲染上都會刷新,因為useEffect使用傳遞給它的函數的新定義。
但是傳遞給setInterval的函數只定義了一次,並且關閉了狀態的舊值。 尚未更新。
使用鈎子進行閉包是棘手的,但是要意識到的是useEffect為每個渲染創建一個新函數,因此每次函數關閉一個新的狀態值時都會創建一個新函數。
然后,訣竅是在useEffect自身內部調用與setInterval相關的代碼,該函數本身取決於state的變化值
React.useEffect(() => {
if(state) {
interval = setInterval(() => {
console.log(state);
}, 1000);
} else {
clearInterval(interval);
}
}, [state]);
或者,最好使用useInterval掛鈎,該掛鈎為您處理這些詳細信息。
setInterval
始終可以訪問組件的第一個渲染的值,因為傳遞給setInterval
的函數會圍繞該值關閉,並且永遠不會重新聲明。 您可以使用自定義鈎子解決此問題:
function useInterval(callback, delay) {
const savedCallback = useRef();
useEffect(() => {
savedCallback.current = callback;
});
useEffect(() => {
function tick() {
savedCallback.current();
}
let id = setInterval(tick, delay);
return () => clearInterval(id);
}, [delay]);
}
該實現和對React Hooks與setInterval
之間不匹配的全面解釋是來自React貢獻者之一Dan Abramov的《使用React Hooks進行setInterval聲明》 。
如果要在狀態更改時重新加載組件,則應按以下方式創建useEffect。
React.useEffect(() => {
console.log('State updated to', state);
}, [state]);
您創建的方式與componentDidMount()
相同,只是將數組作為第二個參數,就像componentDidUpdate()
具有依賴項。 因此,只要您的狀態發生變化,您的組件就會重新渲染。
要解決setTimeout的無窮大調用,您可以在創建函數的地方執行此操作
React.useCallback(() => {
setInterval(() => {
console.log(state);
}, 1000);
})
使用此React將會知道您只想創建一次此函數。
我不是ReactJS專家,但是我想您正在記錄的state
不會刷新,因為它被聲明一次且從未刷新過。 如果React.useState(false)
是為您提供狀態的方法,則應在interval函數中使用它。
這是我要解釋的示例:
const object = { value: false } const notRefreshed = object.value // here we are copying the value const interval = setInterval(() => { const refreshed = object.value // here we are using the reference to copy the latest value console.log("refreshed", refreshed) console.log("notRefreshed", notRefreshed) }, 500) setTimeout(() => object.value = true, 1600) setTimeout(() => clearInterval(interval), 2600)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.