首页 > 解决方案 > 状态变量范围无访问反应时间间隔

问题描述

我正在尝试访问 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))

        }
    }
}

谢谢你,最好的。

标签: javascriptreactjssetinterval

解决方案


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

您可以使用 useRef 来存储 timerId,而不是使用 state。由于 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);

        }
    }
}

推荐阅读