0
votes

I am using axios to get some data from my API but all the request are not in useEffect function. Even more - I am not using useEffect at whole.

Here are parts of my code:

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" />
        )}

So this is calling:

    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);
      });
  };

This is working and it giving me data but in browser I see this error:

index.js:1375 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. in Login (created by Context.Consumer)

I found a lot about this but all of it was related that they put their request methods in useEffect.
P.S.: By the way I am using React hooks (useState but not useEffect in this component)

3
I think that the problem is that you change the state of the component after you push the history, so you mount another component and change the state in a unmounted oneSabbin
maybe your error is in /dashboard and not in /login as you redirect to that page.Tim Gerhard
I agree with @SabbinVikram Thakur
@Sabbin You are right. I put setLoading(false); before push and there is no problem anymore. Thanks!user10477345

3 Answers

1
votes

On your onSubmitLogin you're pushing to another pathname, which provokes the components to unmount and after that, you're trying to update a state from a component already unmounted (that setLoading(false) you have after the history.push).

you can either setLoading(false) before the history push or remove the setLoading from there and create an useEffect to set the loading status to false on the cleaning cycle of that. like:

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

The return of useEffect will execute before changing to another component, like the ComponentWillUnmount lifecycle.

0
votes

You are setting a state for unmounted component so you have to call setLoading before 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);
      });
  };
0
votes

this problem may occurs if the component is unmounted before async function finish and try to set some state var

to fix this you can do something like:

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);
}, []);