状态变量范围无访问反应时间间隔

state variable scope no access react timeInterval

我正在尝试访问 timeInterval 函数内的 intervalId "useState" 变量。但是示波器无法正常工作。 timeInterval 函数中的intervalId 始终为null,这意味着它与赋值延迟无关。

    export function useLocalCommands(length, id) {
    const [intervalId, setIntervalId] = useState(null)
    const [currentIndex, setCurrentIndex] = useState(10)
    const [timeInterval, setTimeInterval] = useState(Constants.READING.READING_TIME_INTERVAL)

    let pauseReading = () => {
        console.log("pause:" + intervalId)
        clearInterval(intervalId)
    }

    let startReading = () => {
        console.log("play")
        pauseReading()
        if (currentIndex < length) {
            setIntervalId(setInterval(() => {
                setCurrentIndex((index) => {
                    if (index < length) {
                        if (id && index % 40 === 0) {
                            Meteor.call('myBooks.updateIndex', id, index, (err, res) => {
                                // show a toast if err 
                            })
                        }
                        return index + 1
                    } else {
                        console.log("pauseReading: " + intervalId)
                        pauseReading();
                    }
                })
            }, timeInterval))

        }
    }
}

谢谢你, 最好的。

IntervalId 从闭包中使用,这就是为什么当 setInterval 运行时,值在声明时采用。但是 setIntervalId 会触发状态更新,即使更新了 state 的值,setInterval 函数中的 timerId 仍会继续指向它从闭包中使用的旧状态。

您可以使用 useRef 来存储 timerId,而不是使用状态。由于 refs 发生了变化,因此它们不受闭包的影响

export function useLocalCommands(length, id) {
    const intervalId = useRef(null)
    const [currentIndex, setCurrentIndex] = useState(10)
    const [timeInterval, setTimeInterval] = useState(Constants.READING.READING_TIME_INTERVAL)

    let pauseReading = () => {
        console.log("pause:" + intervalId.current)
        clearInterval(intervalId.current)
    }

    let startReading = () => {
        console.log("play")
        pauseReading()
        if (currentIndex < length) {
            intervalId.current = setInterval(() => {
                setCurrentIndex((index) => {
                    if (index < length) {
                        if (id && index % 40 === 0) {
                            Meteor.call('myBooks.updateIndex', id, index, (err, res) => {
                                // show a toast if err 
                            })
                        }
                        return index + 1
                    } else {
                        console.log("pauseReading: " + intervalId.current)
                        pauseReading();
                    }
                })
            }, timeInterval);

        }
    }
}