簡體   English   中英

狀態更改后未觸發 useEffect Hook

[英]useEffect Hook Not Firing After State Change

我有兩個兄弟組件通過上下文在反應中共享狀態。 組件之間的共享狀態是一個數組。

如果我在一個組件中更新arr狀態,我希望另一個組件監聽該更新並做相應的事情。 當我在第二個組件中使用useEffect時,我會監聽arr狀態變量的變化。

例如:

// App Component -------
const App = props => {
 const { arr, setArr } = useContext(GlobalContext)
  
 const handleChange = () => {
   const newArr = arr
   [10, 20, 30, 40].map(v => {
     newArr.push(v)
     setArr(newArr)
   })

  return (...)
}

// App2 (Sibling) Component 
const App2 = props => {
  const { arr, setArr } = useContext(GlobalContext)
  const [localArr, setLocalArr] = useState(0)

  useEffect(
    () => {
      updateLocalState()
    },
    // fire if "arr" gets updated
    [arr]
  )

  const updateLocalState = () => {
    setLocalArr(localArr + 1)
  }

  return (...)
}

useEffect掛鈎在初始渲染時觸發,盡管arr的狀態會更新。

我知道向我的狀態變量聲明一個新變量const newArr = arr是一個引用,所以newArr.push(v)在技術上是一個狀態突變。 但是,狀態仍然會更新,不會引發任何警告,並且useEffect什么也不做。

為什么盡管狀態更新了useEffect沒有被調用? 是因為狀態突變嗎?

第二個問題:為什么沒有關於狀態突變的警告或錯誤? 狀態突變是危險的——如果發生這種情況,我希望得到某種警告。

現場演示:

編輯 7wzlo8y4m1

您作為第二個參數傳遞給useEffect的數組僅檢查數組中的元素是否===到上一次渲染中的元素。 const newArr = arr; 將導致newArr === arr因為它不會創建新數組,這不是您想要的。

使用arr中的所有元素創建一個新數組,它將按預期工作。

const App = props => {
 const { arr, setArr } = useContext(GlobalContext)

 const handleChange = () => {
   const newArr = [...arr]
   [10, 20, 30, 40].forEach(v => {
     newArr.push(v)
   })
   setArr(newArr)
 }

  return <>{/* ... */}</>
}

當您想使用 useState 掛鈎更新數組時。 確保將數組傳播到新數組並更新新數組,以便調用監聽此狀態的 useEffect。

當您直接更新數組時,UseEffect不會調用下面的代碼片段。

const [skills, selectedSkills] = useState([])

     const onSelect = (selectedList) => {
            selectedSkills(selectedList)
        }
     useEffect(() => {
            MyLogger('useEffect called')
        }, [skills])

當我們保持對數組的新引用時,UseEffect將調用下面的代碼片段。

const [skills, selectedSkills] = useState([])

     const onSelect = (selectedList) => {
            const tempSelectedList = [...selectedList]
            selectedSkills(tempSelectedList)
        }
     useEffect(() => {
            MyLogger('useEffect called')
        }, [skills])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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