更新后的 useState 值未显示在另一个函数中

Updated useState value not showing in another function

在示例代码 var1 中,无法在 'my_event' 的事件侦听器中访问变量最新值。 setTimeout 将 var1 值更新为 ['a','b'] 但是当调用 doSomething 函数时 onMyEvent 函数中的值仍然打印初始 var1 值 []

任何对该问题的深入了解和修复都将非常有帮助。谢谢

代码示例

import { useEffect, useState } from 'react';

function App() {
  const [var1, setVar1] = useState([])

  const onMyEvent = (e)=>{
    console.log("Detail var1 in onMyEvent: ", var1)//var1 value still prints as [] and not ['a','b']
  }
  useEffect(()=>{
    document.addEventListener('my_event', onMyEvent);
    setTimeout(()=>setVar1(['a','b']),1000)
  },[])
  const doSomething = ()=>{
    document.dispatchEvent(new CustomEvent('my_event', { detail: 5 }));
  }
  return (
    <div className="App">
      <div>{var1.toString()}</div><br/>
      <button onClick={doSomething}>Show Data</button>
    </div>
  );
}

export default App;

您需要将var1添加到useEffect的依赖数组中。这样每次变量 var1 改变时,useEffect 中的内容都会被重新计算。

每次 var1 更改时,它都会为 onMyEvent 函数创建一个事件侦听器,以使用正确的 var1 值来监听您的自定义事件。此外,为了防止无意中创建多个事件侦听器,可以使用 return 函数在 var1 再次更改后取消订阅事件。

import { useEffect, useState } from 'react';

function App() {
  const [var1, setVar1] = useState([])

  const onMyEvent = (e)=>{
    console.log("Detail var1 in onMyEvent: ", var1)//var1 value still prints as [] and not ['a','b']
  }

  useEffect(()=>{
    document.addEventListener('my_event', onMyEvent);
    setTimeout(()=>setVar1(['a','b']),1000)
    return () => {
        document.removeEventListener('my_event', onMyEvent);
    } 
  },[var1])

  const doSomething = ()=>{
    document.dispatchEvent(new CustomEvent('my_event', { detail: 5 }));
  }

  return (
    <div className="App">
      <div>{var1.toString()}</div><br/>
      <button onClick={doSomething}>Show Data</button>
    </div>
  );
}

export default App;

修复由 Arthur 提供。让我讨论一下为什么您的代码无法运行是闭包关闭其上下文的经典问题。在您的情况下,发生的情况是组件 App 首次呈现闭包时:

  const onMyEvent = (e)=>{
    console.log("Detail var1 in onMyEvent: ", var1)//var1 value still prints as [] and not ['a','b']
  }

关闭var1,此时var1的初始值仍然是空数组[]。请记住,具有空依赖项的 useEffect 只会在第一次时导致它 运行,并且最终会将在第一次渲染期间创建的闭包设置为回调。由于闭包将携带它们在创建期间关闭的相同值,因此无论何时调用它们,它们仍然可以访问它们关闭的值。在您的情况下,它是 var1 的空数组。

现在,正如 Arthur Costa 指出的那样,解决方案是将 var1 添加为 useEffect 的依赖项。这将确保每次 var1 更改时都会调用效果,并且您最终将设置一个新的闭包,其中 var1 的新值已关闭。这就是为什么当我们添加正确的依赖项时它会起作用。作为最佳实践,我们需要确保添加在 useEffect 中使用的依赖项。详细文档在这里:https://reactjs.org/docs/hooks-effect.html