Parag Katoch
Parag Katoch

Reputation: 111

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

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

Upvotes: 8

Views: 24783

Answers (1)

Drew Reese
Drew Reese

Reputation: 203408

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

Upvotes: 10

Related Questions