[英]In React, is the difference between simple value state vs object state
[英]React difference of using value in state vs value in object in state
我得到不同的行為取決於我是在 useState 上使用 boolvalue,還是在 useState 的對象內使用 bool 值。
按下按鈕時,第一段代碼將顯示隱藏的文本。 它使用 contextMenuIsOpen 直接在狀態上是一個布爾值,來控制隱藏文本的可見性。
const Parent = () => {
const [contextMenuState, setContextMenuState] = useState({ isOpen: false, x: 0, y: 0, clipboard:null });
const [contextMenuIsOpen, setContextMenuIsOpen] = useState(false);
const openChild = ()=>{
setContextMenuIsOpen(true);
}
return <div><h1>Hello</h1>
<button onClick={openChild}>Open Child</button>
{contextMenuIsOpen &&
<h1>hidden</h1> }
</div>
}
export default Parent;
下一段代碼使用處於狀態的對象的屬性。 當我這樣做時,它不會顯示隱藏的文本。
const Parent = () => {
const [contextMenuState, setContextMenuState] = useState({ isOpen: false, x: 0, y: 0, clipboard:null });
const [contextMenuIsOpen, setContextMenuIsOpen] = useState(false);
const openChild = ()=>{
contextMenuState.isOpen = true;
setContextMenuState(contextMenuState);
}
return <div><h1>Hello</h1>
<button onClick={openChild}>Open Child</button>
{contextMenuState.isOpen &&
<h1>hidden</h1> }
</div>
}
export default Parent;
React 通過檢查對象的引用來檢查對象是否相等。
簡單地說,看看下面的例子。
const x = { a : 1, b : 2}; xa = 3; console.log(x===x);
因此,當您執行以下操作時,
const openChild = ()=>{
contextMenuState.isOpen = true;
setContextMenuState(contextMenuState);
}
您沒有更改contextMenuState
的引用。 因此,狀態沒有真正的變化,並且setContextMenuState
不會導致任何重新渲染。
解決方案:
創建一個新的參考。 一個例子是使用擴展運算符:
const openChild = ()=>{
setContextMenuState({ ...contextMenuState , isOpen : true });
}
您的第二種方法的問題是 React 不會識別該值已更改。
const openChild = () => {
contextMenuState.isOpen = true;
setContextMenuState(contextMenuState);
}
在這段代碼中,您引用了對象的字段,但對象引用本身並沒有改變。 React 只是檢測到contextMenuState
引用了與之前相同的地址,並且從它的角度來看,沒有任何改變,因此不需要重新渲染任何東西。
如果您像這樣更改代碼,則會創建一個新對象,並且舊的 contextMenuState 與新的contextMenuState
不相等,因為 Javascript 已經創建了一個具有新內存地址的新對象(即oldContextMenuState
!== newContextMenuState
)。:
const openChild = () => {
setContextMenuState({
...contextMenuState,
isOpen: true
});
}
這樣 React 將識別狀態變化並重新渲染。
狀態在反應中是不可變的。
您必須使用setContextMenuState()
來更新狀態值。
因為要根據之前的狀態更新狀態,所以最好在setContextMenuState
中傳入一個箭頭函數,其中prev
是之前的狀態。
const openChild = () =>{
setContextMenuState((prev) => ({...prev, isOpen: true }))
}
嘗試改變
contextMenuState.isOpen = true;
至:
setContextMenuState((i) => ({...i, isOpen: true}) )
永遠不要像這樣'contextMenuState.isOpen = true;'改變狀態
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.