首页 > 解决方案 > 状态更改后未触发 useEffect Hook

问题描述

我有两个兄弟组件通过上下文在反应中共享状态。组件之间的共享状态是一个数组。

如果我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

标签: javascriptreactjsreact-hooks

解决方案


您作为第二个参数传递的数组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 <>{/* ... */}</>
}

推荐阅读