[英]React useState hook does not seem to update the state on explicitly calling setter function
[英]useState hook setter incorrectly overwrites state
這是問題所在:我試圖在單擊按鈕時調用 2 個函數。 這兩個函數都更新了 state(我正在使用 useState 掛鈎)。 第一個 function 將 value1 正確更新為“新 1”,但在 1 秒(setTimeout)之后,第二個 function 觸發,並將值 2 更改為“新 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;
歡迎來到封閉地獄。 發生此問題是因為每當調用setState
時, state
都會獲得新的 memory 引用,但函數changeValue1
和changeValue2
,由於關閉,保留舊的初始state
引用。
確保來自changeValue1
和changeValue2
的setState
獲取最新 state的解決方案是使用回調(將之前的 state 作為參數):
import React, { useState } from "react";
const Test = () => {
const [state, setState] = useState({
value1: "1",
value2: "2"
});
const changeValue1 = () => {
setState((prevState) => ({ ...prevState, value1: "new 1" }));
};
const changeValue2 = () => {
setState((prevState) => ({ ...prevState, value2: "new 2" }));
};
// ...
};
你的函數應該是這樣的:
const changeValue1 = () => {
setState((prevState) => ({ ...prevState, value1: "new 1" }));
};
const changeValue2 = () => {
setState((prevState) => ({ ...prevState, value2: "new 2" }));
};
因此,當觸發操作時,您可以通過使用先前的 state 確保您沒有丟失當前 state 中的任何現有屬性。 因此,您也避免了必須管理閉包。
當changeValue2
被調用時,初始 state 被保留,因此 state 回到初始 state 然后寫入value2
屬性。
下次調用changeValue2
時,它會保存 state {value1: "1", value2: "new 2"}
,因此value1
屬性被覆蓋。
您需要一個箭頭 function 作為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>
發生的事情是changeValue1
和changeValue2
從它們創建的渲染中看到 state ,因此當您的組件第一次渲染時,這兩個函數會看到:
state= {
value1: "1",
value2: "2"
}
單擊按鈕時,首先調用changeValue1
並將 state 按預期更改為{value1: "new1", value2: "2"}
。
Now, after 1 second, changeValue2
is called, but this function still see the initial state ( {value1; "1", value2: "2"}
), so when this function updates the state this way:
setState({...state, value2: "new 2" });
你最終會看到: {value1; "1", value2: "new2"}
{value1; "1", value2: "new2"}
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.