我的UI中有一个“卡片”列表,在任何给定时间只能扩展一张卡片。该列表具有一个react-apollo
查询,该查询监视作业列表,并返回标记下一个未完成的作业(nextJobId
)的属性。 useEffect
挂钩跟踪此道具,nextJobId
道具更新时,挂钩也会更新扩展卡。
每张卡的内部都有一个按钮,该按钮会触发react-apollo
突变,从而更新数据库(将job.done
设置为true),进而更新nextJobId
道具。一旦发生这种情况,包含刚刚单击的按钮的卡片就会折叠,从而破坏按钮。
这似乎正在触发以下错误:
react-dom.development.js?61bb:507 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
我相信正在发生的事情是,在完成突变之前,正在更新apollo缓存(如果我向onCompleted
组件添加了Mutation
函数,它将永远不会被触发)。
这是钩子:
useEffect(() => {
client.writeData({
data: {
openVisitId: nextJobId
}
})
}, [nextJobId])
这是突变:
mutation FinishJob($visitId: ID!) {
updateJobInstance(data: { done: true }, where: { id: $visitId }) {
done
id
}
}
到目前为止,我已经解决了两种方法:
1)将setTimeout
添加到挂钩:
useEffect(() => {
setTimeout(() => {
client.writeData({
data: {
liveVisitId: nextJobId,
openVisitId: nextJobId
}
})
})
}, [nextJobId])
不知道为什么会这样。
2)从突变中删除done
(我相信绕过了直接缓存更新),然后使用refetchQueries
重新获取主列表:
mutation FinishJob($visitId: ID!) {
updateJobInstance(data: { done: true }, where: { id: $visitId }) {
id
}
}
<Mutation mutation={FinishJob} refetchQueries={['CardList']}>...</Mutation>
这使我认为某种程度上缓存得到了乐观的更新,这导致在突变真正完成之前销毁了单击的按钮。是这样吗如果是这样,有什么办法告诉react-apollo
在突变真正完成之前不要更新缓存?
答案 0 :(得分:0)
此警告的意思是,您正在尝试更新已卸载组件的状态。 E.x您正在等待请求完成,然后将数据添加到状态中,但是该请求花费了很长时间,因此您正在导航到另一个页面。但是请求仍在完成,因此请求完成后无法将其数据添加到状态中。
因此,为了防止这种情况,最好使用_isMounted
。
function SomeName(){
const _isMounted = false;
useEffect(() => {
_isMounted = true; //this is equivalent of componentDidMoun()
return () => {
_isMounted = false; //this is equivalent of componentWillUnmount()
}
}, [])
}
现在,每次需要更新状态时,都要检查其是否已挂载,以更新状态
if(_isMounted)
{
this.setState({
//your data
})
}