Bar*_*tek 30 javascript reactjs react-hooks
问题出在这里:我试图在单击按钮时调用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;
Run Code Online (Sandbox Code Playgroud)
Alb*_*res 25
欢迎来到封闭地狱。发生此问题的原因setState
是,无论何时调用,state
都会获取新的内存引用,但是由于闭包,函数changeValue1
和会changeValue2
保留旧的初始state
引用。
确保setState
从源changeValue1
并changeValue2
获取最新状态的解决方案是使用回调(将新鲜的当前状态作为参数):
import React, { useState } from "react";
const Test = () => {
const [state, setState] = useState({
value1: "1",
value2: "2"
});
const changeValue1 = () => {
setState((state) => ({ ...state, value1: "new 1" }));
};
const changeValue2 = () => {
setState((state) => ({ ...state, value2: "new 2" }));
};
// ...
};
Run Code Online (Sandbox Code Playgroud)
Dez*_*Dez 18
您的功能应如下所示:
const changeValue1 = () => {
setState((prevState) => ({ ...prevState, value1: "new 1" }));
};
const changeValue2 = () => {
setState((prevState) => ({ ...prevState, value2: "new 2" }));
};
Run Code Online (Sandbox Code Playgroud)
因此,通过在触发操作时使用以前的状态,可以确保您不会丢失当前状态下的任何现有属性。这样也避免了必须管理闭包。
当changeValue2
被调用时,初始状态保持如此状态转变回inital状态,然后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'));
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1210 次 |
最近记录: |