反应上下文状态未更新

Posted

技术标签:

【中文标题】反应上下文状态未更新【英文标题】:React context state not being updated 【发布时间】:2021-09-18 21:36:37 【问题描述】:

我有一个基本的反应上下文,类似于下面:

function IdProvider( children : any) 
  const [id, setId] = useState("DEFAULT_ID")
  
  return (
    <IdContext.Provider value= id, setId >
      children
    </IdContext.Provider>
  )

我用这个提供者包装了我的所有路由,并且有一个组件如下,我想用它来更新 Id:

function UpdateForm() 
  const  id, setId  = useId() // wrapper for the IdContext
 
  const moveToDisplay = (newId: string) => 
    setId(newId)
    window.location.href = "/display/" + id
  

  return (
    <>
      <span onClick=() => moveToDisplay("NEW_ID")>
       Update and redirect
      </span>
    </>
  )

重定向时使用此组件:

function DisplayId(): JSX.Element 
  const  id  = useId()

  useEffect(() => 
    document.title = id
  , [id])

  return (
    <>
      id
    </>
  )

问题是,初始的setId(newId) 不会更新状态,所以当window.location.href = "/display/" + id 被调用时,它会重定向到/display/DEFAULT_ID,而DisplayId 组件在渲染时仍然使用DEFAULT_ID 值。据我了解,useState 是异步的,所以我不完全确定应该如何解决这个问题。我尝试在调用setId 后添加5 秒超时,但id 的值仍然是默认值。

编辑 - 已解决

想通了这个问题,它是相当无关的。我使用单个常量(例如DEFAULT_ID)在各个地方初始化状态,但没有意识到 React 在更新/重新渲染时会检查引用相等。

【问题讨论】:

【参考方案1】:

useContext 提供了通过组件的反应链传递属性的能力。因此,将您的提供者更改为此并确保它正在导出

<IdContext.Provider value=id> 

然后在您的孩子中,您可以通过导入上下文来更新它:

import IdContext from './IdProvider'

和使用上下文:

const [context, setContext] = useContext(IdContext)

然后用新值设置它:

const moveToDisplay = (newId: string) => 
   setContext(newId)
   window.location.href = "/display/" + newId

之后,您通过 DisplayId 以相同的方式导入它并使用该值

【讨论】:

我试过了,它会重定向到正确的 URL,但是当它在 DisplayId 组件的 useEffect 中使用时,它的 id 仍然是 DEFAULT_VALUE 啊,我明白你的意思了!你的 DisplayId 中有 useContext() 吗? 抱歉在代码中犯了一个错误(现已更新),是的,DisplayId 使用相同的上下文,并包含在相同的 IdProvider 中。 酷,如果你想通过 url 来做,你需要做一个window.location.href 来得到它并在最后得到 id。如果你想通过Context.Provider 来实现,这可能是最好的方法,你应该使用setContext() &amp; useContext() 我之前是通过 URL 做的,但它不仅仅是我想要传递的 ID,所以使用上下文更有意义。我已经在执行您的第二个建议,但我无法让它发挥作用。

以上是关于反应上下文状态未更新的主要内容,如果未能解决你的问题,请参考以下文章

反应钩子:useState/context;无法读取未定义的属性“头像”/如何更新嵌套对象

即时反应上下文 api 更新状态

更新的反应上下文值未反映在上一个屏幕中

React - 每当更新反应上下文中的状态时如何调用函数?

来自库的反应上下文未在消费者中更新

在消费者之外更新反应上下文?