如何在不使用useEffect的情况下使用setInterval

时间:2020-10-09 05:11:20

标签: javascript reactjs react-redux

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

如果我将setInterval放入useEffect并最初呈现一次(第12,13,14行),则比它给出正确的输出.. 但是当我直接使用setInterval时,我没有得到正确的输出。 diff打赌他们是什么?
在这两种情况下,我都只调用一次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>
        )
    }

2 个答案:

答案 0 :(得分:3)

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

因此,在这种情况下,setInterval将在每个setCount上重新初始化,因为状态已更改,

一步一步

  • 在第一秒,将有一个setInterval,并调用setCount和组件可以重新渲染
  • 重新进行重编时,从上到下开始执行功能组件,它再次看到setInterval并会触发它,所以现在我们有了两个setIntervals
  • 因此它会每秒增加多个setIntervals,因为我们没有清除它,所以您应该看到浏览器中打印的数字不会花费一秒钟,但是随着时间的流逝会少于一秒钟。
  • li>

通过清除由于useEffect导致的每次重新渲染之前的间隔,您可以在没有setCount的情况下获得预期的结果

创建一个变量来保存设置的间隔code

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);
    ....
 }

reactor具有一个钩子,该钩子可以容纳相同的变量,而无需在每个渲染上重新初始化,将其检出useRef

这是一个code-demo

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

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

intvl.current = setInterval(inc, 1000);
.....

答案 1 :(得分:2)

当您直接使用setInterval时会发生什么情况,因为这是一个函数,它将在状态更改时被调用,因此将再次触发setInterval,依此类推,这实际上会给您不正确的结果,因此您不应在没有使用情况下使用setInterval效果,在卸下时也应清除间隔