这是问题所在:我试图在单击按钮时调用2个函数。这两个函数都会更新状态(我正在使用useState挂钩)。第一个函数将value1正确更新为'new 1',但是在1s(setTimeout)之后触发,第二个函数将值2更改为'new 2',但是!它将value1设置回'1'。为什么会这样呢? 提前致谢!
import React, { useState } from "react";
const Test = () => {
const [state, setState] = useState({
value1: "1",
value2: "2"
});
const changeValue1 = () => {
setState({ ...state, value1: "new 1" });
};
const changeValue2 = () => {
setState({ ...state, value2: "new 2" });
};
return (
<>
<button
onClick={() => {
changeValue1();
setTimeout(changeValue2, 1000);
}}
>
CHANGE BOTH
</button>
<h1>{state.value1}</h1>
<h1>{state.value2}</h1>
</>
);
};
export default Test;
答案 0 :(得分:25)
欢迎来到封闭地狱。发生此问题的原因是,每当调用setState
时,state
都会获得新的内存引用,但是由于关闭,函数changeValue1
和changeValue2
会保留旧的初始{{1 }}参考。
一种用于确保state
和setState
中的changeValue1
获得最新状态的解决方案是使用callback(具有最新的状态作为参数):
changeValue2
答案 1 :(得分:18)
您的功能应如下所示:
.*
因此,通过在触发操作时使用以前的状态,可以确保当前状态下不丢失任何现有属性。这样也避免了必须管理闭包。
答案 2 :(得分:5)
调用changeValue2
时,将保持初始状态,以便该状态返回初始状态,然后写入value2
属性。
此后下一次调用changeValue2
时,它将保持状态{value1: "1", value2: "new 2"}
,因此value1
属性将被覆盖。
setState
参数需要一个箭头功能。
const Test = () => {
const [state, setState] = React.useState({
value1: "1",
value2: "2"
});
const changeValue1 = () => {
setState(prev => ({ ...prev, value1: "new 1" }));
};
const changeValue2 = () => {
setState(prev => ({ ...prev, value2: "new 2" }));
};
return (
<React.Fragment>
<button
onClick={() => {
changeValue1();
setTimeout(changeValue2, 1000);
}}
>
CHANGE BOTH
</button>
<h1>{state.value1}</h1>
<h1>{state.value2}</h1>
</React.Fragment>
);
};
ReactDOM.render(<Test />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 3 :(得分:3)
发生的事情是changeValue1
和changeValue2
都从创建它们的渲染器中看到状态 ,因此当您的组件首次渲染时,这两个函数就会看到:
state= {
value1: "1",
value2: "2"
}
单击按钮时,将首先调用changeValue1
,然后按预期将状态更改为{value1: "new1", value2: "2"}
。
现在,在1秒钟后,将调用changeValue2
,但是此函数仍会看到初始状态({value1; "1", value2: "2"}
),因此当此函数以这种方式更新状态时:
setState({ ...state, value2: "new 2" });
您最终看到:{value1; "1", value2: "new2"}
。