我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

react项目,也可能会使用到setInverval类型代码,这类代码的功用是每隔几秒不间断执行一段代码。如果在这代码体内执行更新state的操作,却发生了意想不到的事情,特殊情况下,会得到state更新失败的结果。那么,如何解决这种问题呢?这就是本文要描述的话题。

苏南大叔:react项目,如何解决setInterval内,useState失效问题? - setInterval-usestate
react项目,如何解决setInterval内,useState失效问题?(图4-1)

大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述在react项目内,基于函数式组件同时使用setIntervaluseState,导致非常奇怪的state无法更新的问题。本文测试环境:create-react-app@5.0.1react@18.2.0react-dom@18.2.0node@16.14.2。再次强调,是函数式组件里面出现的问题,类式组件暂时没有看到类似的问题。

测试代码

本文代码的正确理解,您可能需要查看以下经验文章:

测试代码如下:

import { useState, useRef } from "react";
function Child() {
    const [count, setCount] = useState(0);
    let timerRef = useRef(null);
    if (timerRef.current === null) {
        timerRef.current = setInterval(() => {
            setCount((count + 1) % 6);
        }, 1000);
    }
    const sunan_do = () => {
        setCount((count + 1) % 6);
    };
    return (
        <div className="Child">
            函数式组件测试,{count},
            <button onClick={sunan_do.bind()}>手工加1</button>
        </div>
    );
}
export default Child;

在这个测试代码中,使用的是useState()的方式修改状态值count,变化范围0到5。核心代码如下:

setCount((count + 1) % 6);

在本文中,可以看到:使用按钮可以手动加一,正常运作。但是使用setInterval的时候,状态值从0变成1之后,就停滞不前了。效果上就像是复制了一个count进去,永远就定格在1了。即使通过手工按钮加一了,也会被setInterval变回为定格的1。效果上来看,就像真假美猴王一样,setInterval的那个是个假的....

苏南大叔:react项目,如何解决setInterval内,useState失效问题? - setInterval-usestate-code-1
react项目,如何解决setInterval内,useState失效问题?(图4-2)

解决方案

下面的写法是错误的写法:

setCount((count + 1) % 6);

在这种特殊情况下,这个地方正确的写法,应该改为:

setCount((count) => (count + 1) % 6);

或者

setCount((count) => {
    let count2 = (count + 1) % 6;
    return count2;
});

这里也就解释了useState()文章中的伏笔。

苏南大叔:react项目,如何解决setInterval内,useState失效问题? - setInterval-usestate-code-2
react项目,如何解决setInterval内,useState失效问题?(图4-3)

修改之后就可以正常的在setInterval中修改state数据了。

类式组件中不存在这种问题

可能由于类式组件中修改状态值和函数式组件中修改状态值的函数区别所在,本文中所描述的这种现象,只在函数式组件里面存在,在类式组件中不存在。目标状态值count成功实现了从08的循环任务。

类式组件中的相关测试代码:

import React, { Component } from 'react'
export default class ChildCompare extends Component {
    constructor(props) {
        super(props);
        this.state = { count: 0 };
        this.timerRef = React.createRef(null);
    }
    render() {
        if (this.timerRef.current == null) {
            this.timerRef.current = setInterval(() => {
                let count2 = (this.state.count + 1) % 9;
                // this.setState("count", count2);
                this.setState({ count: count2 });
            }, 1000);
        }
        return (
            <div>类式组件测试,{this.state.count}</div>
        )
    }
}

苏南大叔:react项目,如何解决setInterval内,useState失效问题? - setInterval-usestate-code-3
react项目,如何解决setInterval内,useState失效问题?(图4-4)

相关文章

结束语

更多react经验文章,请参考苏南大叔的博客:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   react