当我的 useEffect 钩子在 react-apollo 突变后被触发时,如何从反应中解决这个警告?
Posted
技术标签:
【中文标题】当我的 useEffect 钩子在 react-apollo 突变后被触发时,如何从反应中解决这个警告?【英文标题】:How do I resolve this warning from react, when my useEffect hook is triggered after a react-apollo mutation? 【发布时间】:2019-08-31 08:25:48 【问题描述】:我的 UI 中有一个“卡片”列表,其中在任何给定时间只能展开一张卡片。这个列表有一个 react-apollo
查询,它监视一个作业列表并返回一个标记下一个未完成作业的道具 (nextJobId
)。此道具由useEffect
钩子跟踪,当nextJobId
道具更新时,该钩子会更新扩展卡片。
在每张卡片内部都有一个按钮,该按钮会触发 react-apollo
突变,它会更新 DB(将 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
在突变真正完成之前不要更新缓存?
【问题讨论】:
好的,将ignoreResults
添加到<Mutation />
组件似乎可以解决此问题(请参阅apollographql.com/docs/react/essentials/mutations#api)。如果有更好的方法,我不会将其标记为已回答。
【参考方案1】:
此警告的意思是您正在尝试更新未安装组件的状态。例如,您正在等待您的请求完成,然后将数据添加到状态,但是请求花费了很长时间,并且您正在导航到另一个页面。但是请求仍在完成中,所以完成后无法将其数据添加到状态中。
所以为了防止它,最好使用_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
)
【讨论】:
谢谢,有道理!它似乎更多地与子组件上的react-apollo
Mutation
组件有关,而不是父组件上的钩子 - 具有突变的子组件在完成之前被销毁(我假设它正在使用引擎盖下的状态)。
以上是关于当我的 useEffect 钩子在 react-apollo 突变后被触发时,如何从反应中解决这个警告?的主要内容,如果未能解决你的问题,请参考以下文章
useEffect 在自定义钩子中使用 ref 缺少依赖项警告
无效的挂钩调用。钩子只能在反应函数组件内部使用...... useEffect,redux
如何在 useEffect 中使用 setTimeout 重置 React 钩子状态
如何将 React 钩子(useContext、useEffect)与 Apollo 反应钩子(useQuery)结合起来