useState 中的变量未在 useEffect 回调中更新 [英] variable in useState not updating in useEffect callback

查看:74
本文介绍了useState 中的变量未在 useEffect 回调中更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 useState 和 useEffect 钩子时遇到问题

I'm having an issue while using useState and useEffect hooks

import { useState, useEffect } from "react";

const counter = ({ count, speed }) => {
    const [inc, setInc] = useState(0);

    useEffect(() => {

        const counterInterval = setInterval(() => {
            if(inc < count){
                setInc(inc + 1);
            }else{
                clearInterval(counterInterval);
            }
        }, speed);

    }, [count]);

    return inc;
}

export default counter;

上面的代码是一个计数器组件,它在 props 中取 count,然后用 0 初始化 inc 并递增它直到它等于 count

Above code is a counter component, it takes count in props, then initializes inc with 0 and increments it till it becomes equal to count

问题是每次我得到 0 时,我都没有在 useEffect 和 setInterval 的回调中得到 inc 的更新值,所以它将 inc 呈现为 1 并且 setInterval 永远不会清楚.我认为 inc 必须关闭 useEffect 和 setInterval 的回调,所以我必须在那里获取更新 inc,所以也许这是一个错误?

The issue is I'm not getting the updated value of inc in useEffect's and setInterval's callback every time I'm getting 0, so it renders inc as 1 and setInterval never get clear. I think inc must be in closure of use useEffect's and setInterval's callback so I must get the update inc there, So maybe it's a bug?

我不能在依赖中传递 inc(在其他类似问题中建议),因为就我而言,我在 useEffect 中设置了 setInterval,因此在依赖数组中传递 inc 会导致无限循环

I can't pass inc in dependency ( which is suggested in other similar questions ) because in my case, I've setInterval in useEffect so passing inc in dependency array is causing an infinite loop

我有一个使用有状态组件的工作解决方案,但我想使用功能组件来实现这一点

I have a working solution using a stateful component, but I want to achieve this using functional component

推荐答案

有几个问题:

  1. 您没有从 useEffect 返回一个函数来清除间隔
  2. 您的 inc 值不同步,因为您没有使用 inc 的先前值.
  1. You're not returning a function from useEffect to clear the interval
  2. Your inc value is out of sync because you're not using the previous value of inc.

一种选择:

const counter = ({ count, speed }) => {
    const [inc, setInc] = useState(0);

    useEffect(() => {
        const counterInterval = setInterval(() => {
            setInc(inc => {
                if(inc < count){
                    return inc + 1;
                }else{
                    // Make sure to clear the interval in the else case, or 
                    // it will keep running (even though you don't see it)
                    clearInterval(counterInterval);
                    return inc;
                }
            });
        }, speed);

        // Clear the interval every time `useEffect` runs
        return () => clearInterval(counterInterval);

    }, [count, speed]);

    return inc;
}

另一种选择是在 deps 数组中包含 inc,这使事情变得更简单,因为您不需要在 setIncinc代码>:

Another option is to include inc in the deps array, this makes things simpler since you don't need to use the previous inc inside setInc:

const counter = ({ count, speed }) => {
    const [inc, setInc] = useState(0);

    useEffect(() => {
        const counterInterval = setInterval(() => {
            if(inc < count){
                return setInc(inc + 1);
            }else{
                // Make sure to clear your interval in the else case,
                // or it will keep running (even though you don't see it)
                clearInterval(counterInterval);
            }
        }, speed);

        // Clear the interval every time `useEffect` runs
        return () => clearInterval(counterInterval);

    }, [count, speed, inc]);

    return inc;
}

甚至还有更简单的第三种方式:在 deps 数组中包含 inc,如果 inc >= count,则在调用 setInterval 之前提前返回:

There's even a third way that's even simpler: Include inc in the deps array and if inc >= count, return early before calling setInterval:

    const [inc, setInc] = useState(0);

    useEffect(() => {
        if (inc >= count) return;

        const counterInterval = setInterval(() => {
          setInc(inc + 1);
        }, speed);

        return () => clearInterval(counterInterval);
    }, [count, speed, inc]);

    return inc;

这篇关于useState 中的变量未在 useEffect 回调中更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆