how to fix missing dependency warning when using useeffect react hook

  • Last Update :
  • Techknowledgy :

If you get data on the base of a specific id, then add in callback useEffect [id]. Then it cannot show you the warning React Hook useEffect has a missing dependency: 'any thing'. Either include it or remove the dependency array Warning: Line 13:8: React Hook React.useEffect has missing dependencies: 'history' and 'currentUser?.role'. Either include them or remove the dependency array react-hooks/exhaustive-deps Now the warning is: React Hook React.useEffect has a missing dependency: 'roleChecking'.

This is our Splunktool team suggestion, we tried and its working fine ✌
useEffect(() => {
   // other code
   ...​
   // eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

If you aren't using fetchBusinesses method anywhere apart from the effect, you could simply move it into the effect and avoid the warning

useEffect(() => {
   const fetchBusinesses = () => {
      return fetch("theURL", {
            method: "GET"
         })
         .then(res => normalizeResponseErrors(res))
         .then(res => {
            return res.json();
         })
         .then(rcvdBusinesses => {
            // some stuff
         })
         .catch(err => {
            // some error handling
         });
   };
   fetchBusinesses();
}, []);

To sum it up I would say that if you are using fetchBusinesses outside of useEffect you can disable the rule using // eslint-disable-next-line react-hooks/exhaustive-deps otherwise you can move the method inside of useEffect

To disable the rule you would write it like

useEffect(() => {
   // other code
   ...

   // eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
5._
useEffect(() => {
   function fetchBusinesses() {
      ...
   }
   fetchBusinesses()
}, [])

In this case, if you have dependencies in your function, you will have to include them in the useCallback dependencies array and this will trigger the useEffect again if the function's params change. Besides, it is a lot of boilerplate... So just pass the function directly to useEffect as in 1. useEffect(fetchBusinesses, []).

const fetchBusinesses = useCallback(() => {
   ...
}, [])
useEffect(() => {
   fetchBusinesses()
}, [fetchBusinesses])

Suggestion : 2

The warning "React Hook useEffect has a missing dependency" occurs when the useEffect hook makes use of a variable or function that we haven't included in its dependencies array. To solve the error, disable the rule for a line or move the variable inside the useEffect hook. One way to get around the warning "React Hook useEffect has a missing dependency" is to disable the eslint rule for a line. The issue in the code snippet is that we're making use of the obj variable inside of the useEffect hook, but we aren't including it in the dependencies array.

1._
Copied!import React, {useEffect, useState} from 'react';

export default function App() {
  const [address, setAddress] = useState({country: '', city: ''});

  // 👇️ objects/arrays are different on re-renders
  const obj = {country: 'Chile', city: 'Santiago'};

  useEffect(() => {
    setAddress(obj);
    console.log('useEffect called');

    // ⛔️ React Hook useEffect has a missing dependency: 'obj'.
    // Either include it or remove the dependency array. eslintreact-hooks/exhaustive-deps
  }, []);

  return (
    <div>
      <h1>Country: {address.country}</h1>
      <h1>City: {address.city}</h1>
    </div>
  );
}
2._
Copied!import React, {useEffect, useState} from 'react';

export default function App() {
  const [address, setAddress] = useState({country: '', city: ''});

  const obj = {country: 'Chile', city: 'Santiago'};

  useEffect(() => {
    setAddress(obj);
    console.log('useEffect called');

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

  return (
    <div>
      <h1>Country: {address.country}</h1>
      <h1>City: {address.city}</h1>
    </div>
  );
}
3._
Copied!import React, {useEffect, useState} from 'react';

export default function App() {
  const [address, setAddress] = useState({country: '', city: ''});

  useEffect(() => {
    // 👇️ move object / array / function declaration
    // inside of the useEffect hook
    const obj = {country: 'Chile', city: 'Santiago'};

    setAddress(obj);
    console.log('useEffect called');
  }, []);

  return (
    <div>
      <h1>Country: {address.country}</h1>
      <h1>City: {address.city}</h1>
    </div>
  );
}
5._
Copied!import React, {useMemo, useEffect, useState} from 'react';

export default function App() {
  const [address, setAddress] = useState({country: '', city: ''});

  // 👇️ get memoized value
  const obj = useMemo(() => {
    return {country: 'Chile', city: 'Santiago'};
  }, []);

  useEffect(() => {
    setAddress(obj);
    console.log('useEffect called');

    // 👇️ safely include in dependencies array
  }, [obj]);

  return (
    <div>
      <h1>Country: {address.country}</h1>
      <h1>City: {address.city}</h1>
    </div>
  );
}
6._
Copied!import React, {useMemo, useEffect, useState, useCallback} from 'react';

export default function App() {
  const [address, setAddress] = useState({country: '', city: ''});

  // 👇️ get memoized callback
  const sum = useCallback((a, b) => {
    return a + b;
  }, []);

  // 👇️ get memoized value
  const obj = useMemo(() => {
    return {country: 'Chile', city: 'Santiago'};
  }, []);

  useEffect(() => {
    setAddress(obj);
    console.log('useEffect called');

    console.log(sum(100, 100));

    // 👇️ safely include in dependencies array
  }, [obj, sum]);

  return (
    <div>
      <h1>Country: {address.country}</h1>
      <h1>City: {address.city}</h1>
    </div>
  );
}

Suggestion : 3

The warning “React Hook useEffect has a missing dependency” occurs when the useEffect hook makes use of a variable or function outside its scope that we haven’t included inside its dependency array. Solve the warning React Hook useEffect has a missing dependency error. Either include it or remove the dependency array. In our case, you can see the only place we are using the fetchUser function is in the useEffect hook so it makes a lot of sense to move the function inside the useEffect hook.

In the snippets below, the count variable is been used in the useEffect hook but we didn’t include it in the dependencies array.

import { useEffect, useState } from 'react';

const TestPage = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const countId = setInterval(() => {
      setCount(count + 1);
    }, 3000);

    return () => clearInterval(countId);

    // ? React Hook useEffect has a missing dependency: 'count'. 
    // Either include it or remove the dependency array.
  }, []);

  return (
    <div>
      <p>You clicked: {count} times </p>
      <button
        style={{ marginRight: 10 }}
        onClick={() => setCount((prev) => prev + 1)}
      >
        Click me
      </button>
    </div>
  );
};

export default TestPage;


2._
import { useEffect, useState } from 'react';

const TestPage = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const countId = setInterval(() => {
      setCount(count + 1);
    }, 3000);

    return () => clearInterval(countId);

    // ? Now React is happy
  }, [count]);

  return (
    <div>
      <p>You clicked: {count} times </p>
      <button
        style={{ marginRight: 10 }}
        onClick={() => setCount((prev) => prev + 1)}
      >
        Click me
      </button>
    </div>
  );
};

export default TestPage;

In the snippets below, since the new state is computed with the previous state I removed the count variable from the useEffect hook and passed a callback function to setCount . The callback function (prev) => prev + 1 receives the previous value and returns the updated value.

With this solution, we can safely remove the count variable from the dependencies array.

import { useEffect, useState } from 'react';

const TestPage = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const countId = setInterval(() => {
      // ? Updater form
      setCount((prev) => prev + 1);
    }, 3000);

    return () => clearInterval(countId);
    // ? React is Happy
  }, []);

  return (
    <div>
      <p>You clicked: {count} times </p>
      <button
        style={{ marginRight: 10 }}
        onClick={() => setCount((prev) => prev + 1)}
      >
        Click me
      </button>
    </div>
  );
};

export default TestPage;


I created two states, one stores the user info, and the other store the query which is the user’s id.

My goal is to fetch a new user whenever the query is incremented by 1 but it doesn’t work as expected since am lying to React by passing an empty dependencies array.

import { useEffect, useState } from 'react';

const TestPage = () => {
  const [query, setQuery] = useState(1);
  const [user, setUser] = useState({});

  const fetchUser = async () => {
    const res = fetch(
      `https://jsonplaceholder.typicode.com/users/${query}`
    ).then((res) => res.json());
    const user = await res;
    setUser(user);
  };

  useEffect(() => {
    fetchUser();
    // ? React Hook useEffect has a missing dependency: 'fetchUser'.
    // Either include it or remove the dependency array.
  }, []);

  if (!user) {
    return <p>loading...</p>;
  }

  return (
    <div>
      <h1>User</h1>
      <p>Id: {user.id}</p>
      <p>Name: {user.name}</p>
      <p>Email: {user.email}</p>
      <div>
        <button onClick={() => setQuery((prev) => prev + 1)}>
          Change User
        </button>
      </div>
    </div>
  );
};

export default TestPage;


Now, let’s move the fetchUser function into the useEffect hook and see if React will complain again.

import { useEffect, useState } from 'react';

const TestPage = () => {
  const [query, setQuery] = useState(1);
  const [user, setUser] = useState({});

  
  useEffect(() => {
    const fetchUser = async () => {
      const res = fetch(
        `https://jsonplaceholder.typicode.com/users/${query}`
      ).then((res) => res.json());
      const user = await res;
      setUser(user);
    };

    fetchUser();
    // ? React Hook useEffect has a missing dependency: 'query'. 
    // Either include it or remove the dependency array
  }, []);

  if (!user) {
    return <p>loading...</p>;
  }

  return (
    <div>
      <h1>User</h1>
      <p>Id: {user.id}</p>
      <p>Name: {user.name}</p>
      <p>Email: {user.email}</p>
      <div>
        <button onClick={() => setQuery((prev) => prev + 1)}>
          Change User
        </button>
      </div>
    </div>
  );
};

export default TestPage;



Suggestion : 4

In this case, if you have dependencies in your function, you have to include them in the useCallback dependencies array. This will trigger the useEffect again if the function's params change. Besides, it has a lot of boilerplate, so you can just pass the function directly to useEffect. 1. Declare function inside useEffect() Hope this solution will solve your problem. To learn more about react, you can check The complete React developer course w/Hooks & Redux course. Sometimes we get this error when we attempt to prevent an infinite loop on a fetch request:

Problem:

Sometimes we get this error when we attempt to prevent an infinite loop on a fetch request:

. / src / components / CarList.js
Line 45: React Hook useEffect has a missing dependency: 'fetchCarList'.
Either include it or remove the dependency array react - hooks / exhaustive - deps

Here is my code:

useEffect(() => {
   fetchCarList();
}, []);

Here is my code:

const fetchCarList = () => {
   return fetch("theURL", {
         method: "GET"
      })
      .then(res => normalizeResponseErrors(res))
      .then(res => {
         return res.json();
      })
      .then(rcvdCarList => {
         // some stuff
      })
      .catch(err => {
         // some error handling
      });
};
5._
    const fetchCarList = useCallback(() => {
       ...
    }, [])
    useEffect(() => {
       fetchCarList()
    }, [fetchCarList])

useEffect(() => {
   fetchCarList()
}, []) // eslint-disable-line react-hooks/exhaustive-deps

Suggestion : 5

I'll be limiting my own use of React Hooks to simple ones like useState to set boolean flags and that sort of thing. If a component ever gets complex enough to need useEffect I treat that as a sign that maybe a class component is just a better fit. I agree with you @luojinghui Please reopen this issue. I want to know the complete solution for this ... Closing Lint is just a temporary solution, the key to this problem is not enough to understand the hook.

1._
React Hook useEffect has a missing dependency: 'setCenterPosition'.Either include it or remove the dependency array.(react - hooks / exhaustive - deps)
2._
function App() {
  const [elePositionArr, setElePositionArr] = useState([
    { left: 0, top: 0 },
    { left: 0, top: 0 },
    { left: 0, top: 0 }
  ]);
  const stageRef = useRef(null);
  const Stage = useRef({ w: 0, h: 0 });
  const currentIndex = useRef(0);

  useEffect(() => {
    // Record the size of the stage
    const stageW = stageRef.current.scrollWidth;
    const stageH = stageRef.current.scrollHeight;

    Stage.current = { w: stageW, h: stageH };

    const index = Math.floor(Math.random() * 3);
    currentIndex.current = index;
    setCenterPosition(index);
  }, []);

  // Centering a block element
  function setCenterPosition(index) {
    let cacheEle = elePositionArr;
    // calc center postion
    const centerOfLeft = Stage.current.w / 2 - 25;
    const centerOfTop = Stage.current.h / 2 - 25;

    cacheEle = cacheEle.map((item, i) => {
      const randomWNum = Math.floor(Math.random() * Stage.current.w) - 50;
      const randomHNum = Math.floor(Math.random() * Stage.current.h) - 50;
      const randomLeft = randomWNum <= 50 ? 50 : randomWNum;
      const randomTop = randomHNum <= 50 ? 50 : randomHNum;
      let newItem;

      if (index === i) {
        newItem = { left: centerOfLeft, top: centerOfTop };
      } else {
        newItem = { left: randomLeft, top: randomTop };
      }

      return newItem;
    });

    setElePositionArr(cacheEle);
  }

  function handleClickLi(index) {
    if (currentIndex.current !== index) {
      setCenterPosition(index);
      currentIndex.current = index;
    }
  }

  return (
    <div className="container">
      <div className="stage" ref={stageRef}>
        {elePositionArr.map((item, index) => (
          <div className="ele" key={index} style={item}>
            {index}
          </div>
        ))}
      </div>
      <ul className="nav">
        {elePositionArr.map((item, index) => (
          <li
            className={currentIndex.current === index ? "active-li" : ""}
            onClick={() => {
              handleClickLi(index);
            }}
            key={"li" + index}
          >
            {index}
          </li>
        ))}
      </ul>
    </div>
  );
}
3._
const ManageTagsModalBody: React.FC<IProps> = ({ children, getTags }) => {
  useEffect(() => {
    getTags();
  }, []);

  return <div>{children}</div>;
};
5._
  useEffect(() => {
     axios.get('http://localhost:8000/api/future-registrations')
        .then((result) => {
           dispatch(initRegistrationsAction(result.data));
        });
  }, []);
6._
  useEffect(() => {
     dispatch(fetchPosts());
  }, []);

Suggestion : 6

React hooks have been around for a while now. Most developers have gotten pretty comfortable with how they work and their common use cases. But there is one useEffect gotcha that a lot of us keep falling for. Hmm, our useEffect seems to have a missing dependency. Oh, well! Let's add it. What's the worst that can happen? 😂 The first and probably most obvious option is to remove the dependency from the useEffect dependency array, ignore the ESLint rule, and move on with our lives. But this is not always possible. Imagine that the user id was somehow dependent on the component props or state.

Because we know we will need to use the user data in other places of our app as well, we also want to abstract the data-fetching logic in a custom React hook.

Essentially, we want our React component to look something like this:

const Component = () => {
  // useUser custom hook
  
  return <div>{user.name}</div>;
};

The second step would be to create our useUser custom hook.

const useUser = (user) => {
   const [userData, setUserData] = useState();
   useEffect(() => {
      if (user) {
         fetch("users.json").then((response) =>
            response.json().then((users) => {
               return setUserData(users.find((item) => item.id === user.id));
            })
         );
      }
   }, []);

   return userData;
};

Note: This is a contrived example for illustrative purpose only! Data-fetching in the real world is much more complicated. If you are interested in the topic, check out my article on how to create a great data-fetching setup with ReactQuery, Typescript and GraphQL.

Let's plug the hook in our React component and see what happens.

const Component = () => {
  const user = useUser({ id: 1 });
  return <div>{user?.name}</div>;
};
5._
const useUser = (user) => {
   const [userData, setUserData] = useState();
   useEffect(() => {
      if (user) {
         fetch("users.json").then((response) =>
            response.json().then((users) => {
               return setUserData(users.find((item) => item.id === user.id));
            })
         );
      }
   }, [user]);

   return userData;
};

So what's next?

In our case, the easiest solution is to take the { id: 1 } object out of the component. This will give the object a stable reference and solve our problem.

const userObject = { id: 1 };

const Component = () => {
  const user = useUser(userObject);
  return <div>{user?.name}</div>;
};

export default Component;