React axios请求要求UseEffect清理功能来取消所有订阅和异步任务

时间:2019-12-06 08:18:12

标签: javascript reactjs axios react-hooks use-effect

我正在使用axios从我的API中获取一些数据,但是所有请求都不在useEffect函数中。甚至更多-我没有完全使用useEffect。

这是我的代码的一部分:

JSX:

<form onSubmit={onSubmitLogin}>
      <div className="form sign-in">
        <h2>Hello again,</h2>
        <div className="div-label">
          <label>
            <span>Email</span>
            <input type="email" onChange={onLoginEmailChange} />
          </label>
        </div>
        <div className="div-label">
          <label>
            <span>Password</span>
            <input type="password" onChange={onLoginPasswordChange} />
          </label>
        </div>
        <p className="forgot-pass">Forgot password?</p>
        {loading && (
          <img
            alt="svg"
            className="loading-img"
            align="middle"
            width={35}
            height={35}
            src={mySvg}
          />
        )}
        {!loading && (
          <input className="submit" type="submit" value="Sign In" />
        )}

这是在打电话:

    const onSubmitLogin = e => {
    e.preventDefault();
    setLoading(true);

    axios
      .get(
        `http://myapiURL/?email=${loginEmail}&password=${loginPassword}`
      )
      .then(res => {
        console.log(res);
        if (res.status === 200) {
          console.log("here");
          history.push({
            pathname: "/dashboard",
            state: res.data
          });
          setLoading(false);
        }
      })
      .catch(e => {
        console.log(e);
      });
  };

这可以正常工作并且可以给我数据,但是在浏览器中我看到此错误:

  

index.js:1375警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。       登录中(由Context.Consumer创建)

我对此有很多发现,但是所有与他们将请求方法放入useEffect有关。
P.S .:顺便说一下,我正在使用React钩子(在此组件中使用useState而不是useEffect)

3 个答案:

答案 0 :(得分:0)

在onSubmitLogin上,您将推到另一个路径名,该路径名将导致要卸载的组件,然后,您尝试从已卸载的组件(在历史记录之后具有setLoading(false)的状态)更新状态。 )。

您可以在历史记录推送之前设置setLoading(false)或从此处删除setLoading并创建useEffect,以在该清理周期中将加载状态设置为false。喜欢:

useEffect(() => {
  return () => {
    setLoading(false);
  }
}, [])

useEffect的返回将在更改为另一个组件(例如ComponentWillUnmount生命周期)之前执行。

答案 1 :(得分:0)

您正在为未安装的组件设置状态,因此必须在setLoading之前调用history.push

const onSubmitLogin = e => {
    e.preventDefault();
    setLoading(true);

    axios
      .get(
        `http://myapiURL/?email=${loginEmail}&password=${loginPassword}`
      )
      .then(res => {
        console.log(res);
        if (res.status === 200) {
          console.log("here");
          setLoading(false);
          history.push({
            pathname: "/dashboard",
            state: res.data
          });
        }
      })
      .catch(e => {
        console.log(e);
      });
  };

答案 2 :(得分:0)

如果在异步函数完成之前卸载组件并尝试设置一些状态变量,可能会出现此问题

要解决此问题,您可以执行以下操作:

React.useEffect(() => {
    let isSubscribed = true;
    axios
      .get(
        `http://myapiURL/?email=${loginEmail}&password=${loginPassword}`
      )
      .then(res => {
          console.log(res);
          if (res.status === 200) {
            history.push({
               pathname: "/dashboard",
               state: res.data
           });
           // check if this component still mounted
           if (isSubscribed) {
             setLoading(false);
           }
         }
      });

    return () => (isSubscribed = false);
}, []);