反应上下文状态未更新
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() & useContext()
我之前是通过 URL 做的,但它不仅仅是我想要传递的 ID,所以使用上下文更有意义。我已经在执行您的第二个建议,但我无法让它发挥作用。以上是关于反应上下文状态未更新的主要内容,如果未能解决你的问题,请参考以下文章