我尝试在使用 useState
Hook 时以编程方式更改状态。
我是这样定义的:
const [data, setData] = React.useState({
text: "Hello StackOverflow!",
someNumber: 2
});
出于测试目的,我创建了一个每秒增加 someNumber
的间隔。
setInterval(() => {
setData({ ...data, someNumber: data.someNumber + 1 });
}, 1000);
当我现在安装组件时,文本开始以不同的数字快速闪烁。我猜间隔已启动多次,但我不知道为什么。这是我使用新钩子(Hook)的第一个项目。
可以找到我的代码的完整示例 on code sandbox snippet
如果链接失效,这里是组件:
import React from "react";
import TextField from "@material-ui/core/TextField";
export default function StateTextFields() {
const [data, setData] = React.useState({
text: "Hello StackOverflow!",
someNumber: 2
});
setTimeout(() => {
setData({ ...data, text: "How are you?" });
}, 1000);
setInterval(() => {
setData({ ...data, someNumber: data.someNumber + 1 });
}, 1000);
return (
<TextField
id="standard-name"
label="Name"
value={data.text + " " + data.someNumber}
margin="normal"
/>
);
}
最佳答案
将 setInterval
移至 useEffect
内。这将阻止它在每次渲染时创建新的间隔。
React.useEffect(() => {
setInterval(() => {
setData(prevState => ({ ...prevState, someNumber: prevState.someNumber + 1 }));
}, 1000);
setTimeout(...)
},[])
这将使这些函数仅在组件安装时运行一次。
无条件调用修改功能组件内部状态的函数就像在类组件的渲染中执行相同的操作一样。它将修改状态,这会导致重新渲染,这将无限地修改状态,依此类推。
您需要使用prevState
回调来更新。这是因为 useEffect
没有监听对 data
所做的更改,例如 useEffect(() => {}, [data])
使 数据
变得陈旧。但我们也不想更改它来监听更改,因为这会导致您的间隔再次无限创建。因此,我们使用 prevState
它始终使用最新的状态副本。
关于reactjs - 无法使用 useState 以编程方式更改组件的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58859685/