[英]React hooks: new state value not reflecting in setInterval callback
我有一個函數反應組件,它有一個從 10000 開始並變為 0 的計數器。
我在組件安裝期間使用 useEffect 鈎子設置 setInterval 回調。 然后回調更新計數器狀態。
但我不知道為什么, count
數值永遠不會減少。 每次回調運行count
為 10000。
(我正在使用 react 和 react-dom 版本16.8.3
)
功能組件如下:
import React, { useState, useEffect, useRef } from 'react'
const Counter = () => {
const timerID = useRef()
let [count, setCount] = useState(10000)
useEffect(() => {
timerID.current = setInterval(() => {
//count here is always 10000
if (count - 1 < 0) {
setCount(0)
} else {
setCount(count - 1)
}
}, 1)
}, [])
return <h1 className="counter">{count}</h1>
}
export default Counter
這是codeandbox的鏈接: link
您需要注意count
變化,並清理您的useEffect()
:
useEffect(() => {
timerID.current = setInterval(() => {
if (count - 1 < 0) {
setCount(0)
} else {
setCount(count - 1)
}
}, 100)
return () => clearInterval(timerID.current);
}, [count])
正如@Pavel 所提到的,Dan Abramov 在這里解釋了原因。
有2個選項:
1) 在依賴項中包含count
這並不理想,因為這意味着每次更改count
都會創建一個新的setInterval
,因此您需要在每次渲染時清理它,例如:
useEffect(() => {
timerID.current = setInterval(() => {
//count here is always 10000
if (count - 1 < 0) {
setCount(0)
} else {
setCount(count - 1)
}
}, 1)
return () => clearInterval(timerID.current) // Added this line
}, [count]) // Added count here
2)在setInterval
回調函數中添加count
。
這是間隔的最佳方法,因為它避免了一直設置新的間隔。
useEffect(() => {
timerID.current = setInterval(() => {
// count is used inside the setCount callback and has latest value
setCount(count => {
if (count - 1 < 0) { // Logic moved inside the function, so no dependencies
if (timerID.current) clearInterval(timerID.current)
return 0
}
return count - 1
})
}, 1)
return () => {
if (timerID.current) clearInterval(timerID.current) // Makes sure that the interval is cleared on change or unmount
}
}, [])
這是沙箱鏈接
如您所說,您在組件安裝時聲明了效果功能。 所以在那個時間值存儲的范圍內,count 等於 10000。這意味着每次執行時間間隔函數都會從閉包 (10000) 中獲取計數值。 正確地做到這一點實際上非常困難。 丹寫了整篇關於它的博客文章
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.