react项目,如何解决setInterval内,useState失效问题?
发布于 作者:苏南大叔 来源:程序如此灵动~react
项目,也可能会使用到setInverval
类型代码,这类代码的功用是每隔几秒不间断执行一段代码。如果在这代码体内执行更新state
的操作,却发生了意想不到的事情,特殊情况下,会得到state
更新失败的结果。那么,如何解决这种问题呢?这就是本文要描述的话题。
大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔和计算机代码的故事。本文描述在react
项目内,基于函数式组件同时使用setInterval
和useState
,导致非常奇怪的state
无法更新的问题。本文测试环境:create-react-app@5.0.1
,react@18.2.0
,react-dom@18.2.0
,node@16.14.2
。再次强调,是函数式组件里面出现的问题,类式组件暂时没有看到类似的问题。
测试代码
本文代码的正确理解,您可能需要查看以下经验文章:
- 禁用StrictMode,https://newsn.net/say/react-strict-mode.html
- 使用Ref.current,https://newsn.net/say/react-ref.html
- 函数式组件修改state,https://newsn.net/say/react-usestate.html
测试代码如下:
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
的那个是个假的....
解决方案
下面的写法是错误的写法:
setCount((count + 1) % 6);
在这种特殊情况下,这个地方正确的写法,应该改为:
setCount((count) => (count + 1) % 6);
或者
setCount((count) => {
let count2 = (count + 1) % 6;
return count2;
});
这里也就解释了useState()
文章中的伏笔。
修改之后就可以正常的在setInterval
中修改state
数据了。
类式组件中不存在这种问题
可能由于类式组件中修改状态值和函数式组件中修改状态值的函数区别所在,本文中所描述的这种现象,只在函数式组件里面存在,在类式组件中不存在。目标状态值count
成功实现了从0
到8
的循环任务。
类式组件中的相关测试代码:
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>
)
}
}
相关文章
- https://newsn.net/say/react-strict-mode.html
- https://newsn.net/say/react-ref.html
- https://newsn.net/say/react-useref.html
- https://newsn.net/say/react-createref.html
- https://newsn.net/say/react-usestate.html
结束语
更多react
经验文章,请参考苏南大叔的博客:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。