skip to Main Content

When making a request and setting the response to some state, the useEffect seems to loop infinitely. The problem with the repeating loop is that useEffect requires an array of dependencies to know when to run when the dependencies change.

This can be avoided by leaving the dependency causing the infinite loop out or providing an empty dependency array[], but the linter will give a warning that the useEffect is missing a dependency, which makes it seem like it should be included, but again that causes the repeating loop.

Is useEffect supposed to be used for these types of tasks?

// E.g this will cause an infinite loop

const [data, setData] = useState(null);

useEffect(() => {
  const response = *do some fetching via HTTPS request*

  setData(response);
}, [data])

3

Answers


  1. The useEffect hook allows you to perform side effects in your components. Fetching data by http requests is of course one of the things that can be done.

    I think the problem is, whenever you fetch new data and update the state, the data variable is changed, and the callback function in useEffect() gets triggered as data is in the dependency array. Then, you fetch data again causing an infinite loop. It works pretty much like a recursion without a base case.

    To solve the problem, I guess you can either skip the dependency array, pass an empty array or pass the array with another variable that will not be changed in the callback function.

    If you skip the dependency array,

    useEffect(() => {
      const data = *do some fetching via HTTPS request*
    
      setData(data);
    });
    

    the callback function will run on every render, but it won’t cause an infinite loop.

    If you pass an empty array,

    useEffect(() => {
      const data = *do some fetching via HTTPS request*
    
      setData(data);
    }, []);
    

    the callback function runs only once after the initial render.

    If you pass the array with another variable instead,

    useEffect(() => {
      const data = *do some fetching via HTTPS request*
    
      setData(data);
    }, [someDependency]);
    

    the callback function will only be triggered when someDependency is updated. But someDependency should not be updated within the useEffect() callback function. It can be updated by some user interactions. It depends on what you want to do and what’s the condition of fetching data.

    You can also see some examples of passing different dependency arrays here.

    Hope this helps!

    Login or Signup to reply.
  2. Not sure if I understood the question, but what I think you should do is this:

    useEffect(() => {
      const data = *do some fetching via HTTPS request*
    
      setData(data);
    }, []) //changed this line
    

    As you can see, the dependency array is present, but empty, meaning that the useEffect will be called only once, on the intial render of the component. (Actually twice if you are using React.StrictMode, but that is not relevant to this topic).

    Login or Signup to reply.
  3. The hot fix is you can disable that particular rule by adding a single line.

    const [data, setData] = useState(null);

    useEffect(() => {
    const res = do some fetching via HTTPS request

    setData(res);
    }, []) // eslint-disable-line react-hooks/exhaustive-deps

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search