8

I am making an api call from useEffect hook

function ChangePassword(props) {
    const token = props.match.params.token;

    const [state, setState] = useState({
        password: "",
        confirmPassword: "",
    });
    const [status, setStatus] = useState({
        loaded: false,
        auth: false,
    });

    useEffect(() => {
        let { auth } = status;

        axios
            .get(
                `http://localhost:2606/api/hostler/changepassword?token=${token}`
            )
            .then((res) => {
                console.log("res", res);
                auth = res.status === 202;
            })
            .then(() => setStatus({ auth, loaded: true }))
            .catch((err) => console.log("err", err));
    },[]);

    return (
        // code
    );
}

But react gives warning

React Hook useEffect has missing dependencies: 'status' and 'token'. Either include them or remove the dependency array react-hooks/exhaustive-deps

also adding status to dependency array will result in an infinite loop because setStatus is called inside of useEffect

Parag Katoch
  • 111
  • 1
  • 2
  • 4
  • When do you want the effect callback to run? Only on component mount? Want the GET request to only be made when `auth` is false? – Drew Reese Jun 26 '21 at 07:20
  • @DrewReese callback should run only when component mounts and auth should be false for the GET request – Parag Katoch Jun 26 '21 at 07:25
  • @ParagKatoch then simply add ```// eslint-disable-next-line react-hooks/exhaustive-deps``` before line containing ```},[]);```. – brc-dd Jun 26 '21 at 07:27
  • Moreover, if you want it to be false then why not simply declare `let auth = false` instead? – brc-dd Jun 26 '21 at 07:29
  • @brc-dd but this https://github.com/facebook/create-react-app/issues/6880#issuecomment-485912528 say's its a mistake – Parag Katoch Jun 26 '21 at 07:30
  • 1
    @ParagKatoch then do this: `let auth = false`, and add `token` to deps array. – brc-dd Jun 26 '21 at 07:33
  • I am not sure if it has any harms(time or google will show) but i simply remove this part from useEffect : ,[ ] – cansu Sep 24 '21 at 19:02
  • Does this answer your question? [How to fix missing dependency warning when using useEffect React Hook](https://stackoverflow.com/questions/55840294/how-to-fix-missing-dependency-warning-when-using-useeffect-react-hook) – steven7mwesigwa Jan 31 '22 at 13:37

1 Answers1

10

If you want the effect to run only once when the component mounts then it is technically correct to specify an empty dependency array. However, the React-hooks linting rules aren't able to differentiate this case. You can disable the rule specifically for that line.

I notice also that your effect doesn't really have a dependency on status.auth since you are always mutating/overwriting it anyway, you can remove it and just set the new auth state value.

useEffect(() => {
  axios
    .get(
      `http://localhost:2606/api/hostler/changepassword?token=${token}`
    )
    .then((res) => {
      console.log("res", res);
      setStatus({ auth: res.status === 202, loaded: true })
    })
    .then(() => )
    .catch((err) => console.log("err", err));

  // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

However, disabling the rule will possibly mask future updates, so you'll want to include token as a dependency. If the component rerenders/remounts and the token has changed you'll want to ensure you are working with the latest values. In other words, you don't want to use stale state/prop values.

useEffect(() => {
  axios
    .get(
      `http://localhost:2606/api/hostler/changepassword?token=${token}`
    )
    .then((res) => {
      console.log("res", res);
      setStatus({ auth: res.status === 202, loaded: true })
    })
    .then(() => )
    .catch((err) => console.log("err", err));

}, [token]);

If you want to only run the GET request when auth is false then it would be a dependency and should be included. And so you don't render loop if res.status === 202 resolves false, also include a condition that you haven't completed loading yet.

useEffect(() => {
  !auth && !loaded && axios
    .get(
      `http://localhost:2606/api/hostler/changepassword?token=${token}`
    )
    .then((res) => {
      console.log("res", res);
      setStatus({ auth: res.status === 202, loaded: true })
    })
    .then(() => )
    .catch((err) => console.log("err", err));

}, [auth, loaded, token]);
Drew Reese
  • 165,259
  • 14
  • 153
  • 181