反应上下文状态未更新

时间:2021-07-08 12:04:15

标签: reactjs typescript react-hooks react-context react-state

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

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 个答案:

答案 0 :(得分:0)

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 以相同的方式导入它并使用该值