拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 IonicReactOvermind无法对未安装的组件执行React状态更新

IonicReactOvermind无法对未安装的组件执行React状态更新

白鹭 - 2022-02-14 2142 0 0
赏金在 6 天后到期此问题的答案有资格获得 100声望赏金。 Lars Flieger正在从有信誉的来源寻找答案

我使用Overmind和离子反应:

表 1:

const { count } = useAppState()
const { increaseCount } = useActions()

return
<IonPage>
  <IonContent>
    <IonRouterLink routerLink='/tab1/page1'>1. Go to another page</IonRouterLink> // Go to page 1
    <IonText><p>{count}</p></IonText>
    <IonButton onClick={() => increaseCount()}>4. Increase again</IonButton>
  </IonContent>
</IonPage>

第2页:

const { count } = useAppState()
const { increaseCount } = useActions()

return
<IonPage>
  <IonContent>
    <IonBackButton defaultHref="/" /> // Go back to tab 1
    <IonText><p>{count}</p></IonText>
    <IonButton onClick={() => increaseCount()}>4. Increase again</IonButton>
  </IonContent>
</IonPage>

当我这样做时:

  1. 转到另一个页面
  2. 增加计数(修改状态)
  3. 回传主页面
  4. 增加计数(修改状态)==> 进入控制台,出现错误
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 a useEffect cleanup function.

我创建了这个最小复制代码:https ://github.com/dopeshot/ionic-overmind-cant-perform-state-update

我还制作了一个关于该问题的短视频:https ://www.youtube.com/watch?v=5w6r1_lxoS8

我该如何解决这个问题?

uj5u.com热心网友回复:

这个问题是 overmind-react 库中的一个错误。如果您查看源代码,您会看到当组件卸载时它们没有将 设定mountedRef.current为 false,因此当状态更改时,它会尝试重新渲染卸载的组件。它应该在这里 https://github.com/cerebral/overmind/blob/cb095ffa0cd49504fed6bbc99054d89ba9b92ea3/packages/overmind-react/src/index.ts#L139

您可以克隆存盘库,将以下更改添加到代码中,并将依赖项指向您在 git 存盘库中的版本(或发布您自己的包)

    return () => {
        mountedRef.current = false;
        overmind.eventHub.emitAsync(EventType.COMPONENT_REMOVE, {

最好的办法是打开一个 GitHub 问题,如果可能的话,用那个小改动打开 PR。但我不希望它很快得到解决,因为它似乎是一个只在开发中发生的问题。

uj5u.com热心网友回复:

如果组件尚未安装,则无需更新回呼中的状态。

作为错误状态:

解决方案

宣告 let isMounted = trueinside useActions(或者useEffectuseAction不建议使用,并且不再真正支持,您可以阅读redux 的创建者对此的评论),一旦组件被卸载,它将在清理回呼中更改。在状态更新之前,您现在有条件地检查此变量:

useEffect(() => {
  let isMounted = true;               // note mutable flag
  someAsyncOperation().then(data => {
    if (isMounted) setState(data);    // add conditional check
  })
  return () => { isMounted = false }; // cleanup toggles value, if unmounted
}, []);                               // adjust dependencies to your needs

更彻底的解决方案:自定义useAsyncHook 我们可以将所有样板封装到自定义 Hook 中,如果组件卸载或依赖值之前发生更改,它会自动中止异步函式:

function useAsync(asyncFn, onSuccess) {
  useEffect(() => {
    let isActive = true;
    asyncFn().then(data => {
      if (isActive) onSuccess(data);
    });
    return () => { isActive = false };
  }, [asyncFn, onSuccess]);
}
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *