簡體   English   中英

反應在狀態中使用值與在狀態中使用對象中的值的差異

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM