如何在react中使用setInterval而不使用useEffect

mee*_*iya 0 javascript reactjs react-redux

如果我使用 setInterval(line 15) 而不使用 useEffect ,那么它给出的结果是 2^n-1(0,1,3,7,15,31,63...) 而不是(0,1,2,3,4, ..)。所以我有一些问题
1)为什么当我直接调用setInterval而不使用useEffect时我会得到该输出2)如果我更改setCount(第9行)并且它通过直接使用setInterval而不使用useEffect给出正确的输出(就像我所做的那样)有什么办法3)如果没有useEffcet就不可能使用setInterval,那么为什么不可能呢?

如果我将 setInterval 放入 useEffect 中并最初渲染一次(第 12,13,14 行),那么它会给出正确的输出......但是当我直接使用 setInterval 时,我没有得到正确的输出。什么是差异赌注?
在这两种情况下,我都调用 setInterval 一次,但输出是 diff。

import React, {useEffect, useState } from 'react'
    
    export default function IncorrectDependency() {
    
    const [count,setCount]=useState(0)
    
    const inc=()=>{
        // console.log(count)
        setCount(preVal=>preVal+1)
    //    setCount(count+1)
    }
    // useEffect(()=>{
    //     setInterval(inc,1000)},[]
    // )
    setInterval(inc,1000)
    
        return (
            <div>
                <h1>{count}</h1>
               
            </div>
        )
    }
Run Code Online (Sandbox Code Playgroud)

K.T*_*ess 7

当我们设置状态时,功能组件将从上到下重新执行,但是当我们使用 useState、useCallbacks 等时。它们不会重新初始化为变量、函数、

因此在这种情况下,由于状态发生了变化,setInterval将重新初始化每个,setCount

一步步

  • 第一秒会有一个setInterval,调用setCount,组件准备重新渲染
  • 当重新渲染时,开始从上到下执行它setInterval再次看到的功能组件,并且它会触发它,所以现在我们有两个setIntervals
  • 所以它会每秒添加多个setIntervals,因为我们没有清除它,所以你应该看到浏览器中打印的数字不会花费一秒,但随着时间的推移,会少于一秒。

您可以实现预期结果,而无需useEffect清除每次重新渲染时的先前间隔,这是由于setCount

创建一个变量来保存设置的间隔,代码

const interval = null;
//this should be declare out side the component,
//because if we declare it inside the component it will redeclare,
//and the reference to the previous setInterval will be lost in that case no-way to clear the setInterval.
export default function IncorrectDependency() {
    ....
    if (interval) {
        clearInterval(interval);
    }

    interval = setInterval(inc, 1000);
    ....
 }
Run Code Online (Sandbox Code Playgroud)

或者,react 有一个钩子,可以保存相同的变量,而无需在每个渲染上重新初始化,请查看useRef

这是一个代码演示

const intvl = useRef(null);
....

if (intvl?.current) {
    clearInterval(intvl.current);
}

intvl.current = setInterval(inc, 1000);
.....
Run Code Online (Sandbox Code Playgroud)