处理 window 事件时的本地状态值错误 (React)

Wrong local state value when a handling a window event (React)

我有一个状态值 ccFormDetails,其中一个空对象作为默认值。

  const [ccFormDetails, setCCFormDetails] = useState({})

首先 useEffect,我调用了一个函数,用相关数据填充 ccFormDetails

  const getCCFormData = async () => {
    const ccFormResult = await ContractService.getContractsCCFormData()
    const { ccFormData } = ccFormResult
    setCCFormDetails(ccFormData)
  }

在第二个 useEffect 中,我创建了一个名为 message 的事件并为其分配了一个 handleCgEvent 处理程序。

  useEffect(() => {
    window.addEventListener('message', handleCgEvent)
    return () => window.removeEventListener('message', handleCgEvent)
  }, [])

我正在渲染一个带有提交按钮的 iframe,单击该按钮会发出 message 事件。

然后,当我单击 iframe 中的 sumbit 按钮时,handleCgEvent 处理程序将触发并应提取 ccFormDetails 的正确(更新的、已检测的)值。 (我可以在 React 组件树中看到正确填充)

  const handleCgEvent = e => {
    if (e.data === 'reload_cg') {
      console.log('fail')
    }

    if (e.data['event_id'] === 'cg-success') {
      console.log('success')
      console.log('ccFormDetails1 ', ccFormDetails)
    }
  }

但我得到的是 {} 表示原始默认状态。 根据我对 React 的了解,这不应该发生。 我是否缺少 something/Does 事件处理混乱状态?

这里的问题是您正在使用安装组件时创建的 handleCgEvent,并且 ccFormDetails 使用其默认值封装在其中。为了获得最新状态,您将不得不使用 useRef。类似于:

  const [ccFormDetails, setCCFormDetails] = useState({})
  const formRef = useRef();

  formRef.current = ccFormDetails;

  const handleCgEvent = e => {
    if (e.data === 'reload_cg') {
      console.log('fail')
    }

    if (e.data['event_id'] === 'cg-success') {
      console.log('success')
      console.log('ccFormDetails1 ', formRef.current)
    }
  }

  useEffect(() => {
    window.addEventListener('message', handleCgEvent)
    return () => window.removeEventListener('message', handleCgEvent)
  }, []);

如果您可以添加和删除事件侦听器,那么我将添加 [ccFormDetails] 作为依赖项,假设在其属性更改时重新创建整个对象。

要进一步阅读闭包中的陈旧值,这是一篇很棒的博客文章:https://dmitripavlutin.com/react-hooks-stale-closures/