React Hooks:从普通事件处理程序启动时如何丢弃异步结果?

时间:2019-05-13 06:27:19

标签: reactjs react-hooks

我试图了解新的React hooks API(目前我正在使用React 16.8.x)。

我发现useEffect()钩使得当用户执行导致不再显示组件的操作时,很容易丢弃服务器调用的结果,如(A)< / strong>:

useEffect(()=>{
  let mounted = true;
  setInvocation("processing");
  MuiServiceApi.instance.
    invokeProcessingMethod(details.endpoint, parsedPayload).
    then(result=> mounted && setInvocation(result)).
    catch(e=> setInvocation({message: "while updating DB", problem: e}));
  return ()=>{mounted = false};
}, []);

但是,根据(B)

,当我从常规表单事件中进行呼叫时如何实现类似的行为:
<form onSubmit={()=>{
  setInvocation("processing");
  MuiServiceApi.instance.
    invokeProcessingMethod(details.endpoint, parsedPayload).
    then(result=> setInvocation(result)).
    catch(e=> setInvocation({message: "while updating DB", problem: e}));
}}>

如果用户在首次显示组件时正在执行调用时将其关闭(即(A)逻辑),则结果将被彻底丢弃。

如果用户在处理过程中关闭了组件,则在单击实际的提交按钮((B)逻辑)后,将出现控制台警告,例如:

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.

这并不是什么大不了的事情-实际上,在预钩class API下,我从来没有理会丢弃未安装组件的结果,因为这太麻烦了。

但是此练习的重点是学习Hooks API,所以我想知道如何为onSubmit处理程序执行此操作。

我尝试用mounted定义useState(),但是我看不到它的工作方式,

const [mounted, setMounted] = React.useState(false);
useEffect(()=>{
  setMounted(true);
  setInvocation("processing");
  MuiServiceApi.instance.
    invokeProcessingMethod(details.endpoint, parsedPayload).
    then(result=> {
      if( mounted ){
        console.log("result used");
        setInvocation(result);
      }
      else {
        console.log("result ignored because dismounted");
      }
    }).
    catch(e=> setInvocation({message: "while updating DB", problem: e}));
  return ()=>{
    console.log("dismounted");
    setMounted(false)
  };
}, []);

我现在回想起来,它是行不通的,因为mounted的{​​{1}}值是由闭包捕获的;因此false处理程序将永远不会看到then

应该在这里使用“减少器”或“回调”吗?该文档在“基本”钩子之后变得非常模糊,因此我不确定是否应该这样做。

要重新陈述问题:应如何重构以下组件,以使mounted == true then()内的form处理程序不会导致有关更新状态的警告(如果该组件已经存在)被卸载?


下面的完整组件(在onSubmit中)

Typescript

1 个答案:

答案 0 :(得分:0)

一种解决方法是通过React useRef API将mounted从变量更改为引用。

使用const mounted = React.useRef(false)声明引用,然后在以前的代码使用变量的任何地方使用mounted.current

始终通过Ref访问current值意味着该组件的效果和事件处理程序都绑定到Ref所指向的单个“当前”值,而不是呈现组件时变量的副本。