Search code examples
reactjsreact-hooksuse-effectuse-state

React useEffect including the missing dependency will break it


I'm working on a React App with some useEffect hooks. Let's say I've got the following code:

import React, { useState, useEffect } from 'react';

export default () => {
  const [fooArr, setFooArr] = useState([]);
  const [barObj, setBarObj] = useState({});

  return <h1>{barObj.name + " " + barObj.status}</h1>
}

But, now the problem. fooArr gets changed somewhere else, and I want to update barObj when fooArr changes. I did this as below:

import React, { useState, useEffect } from 'react';

export default () => {
  const [fooArr, setFooArr] = useState([]);
  const [barObj, setBarObj] = useState({});

  // >>> some fetching and setting of 'fooArr' here <<<

  useEffect(() => {
    setBarObj(barObj => {
      let _barObj = { ...barObj };
      _barObj.status = fooArr[1];
      return _barObj;
    })
  }, [fooArr]);

  return <h1>{barObj.name + " " + barObj.status}</h1>
}

However, this gives me the following error React Hook useEffect has a missing dependency: 'barObj' and 'setBarObj'. Either include it or remove the dependency array. I know exactly what this means, but when I include it I get an infinite re-render loop because it keeps updating itself. I've got // eslint-disable-line now next to the dependency array to ignore this. But I feel like that should never be done.

How should I handle this? I would like to not have an error message but to also not have an infinite re-render loop..

Example with more code that is like my code:

useEffect(() => {
  setBarObj(prevBarObj => {
    let _barObj = { ...prevBarObj };
    if(_barObj.status.includes('hello') {
      _barObj.status += "world"
    } else {
      _barObj.status = "other"
    }
    return _barObj;
  })
}, [fooArr])

Solution

  • This should work fine:

    useEffect(() => {
      setBarObj(barObj => ({
        ...barObj,
        status: fooArr[1]
      })
    }, [fooArr]);
    

    I also recommend you to look into my another post to resolve the issue with fetching data and will avoid missing dependency error.


    As per your comment, you can do like:

    useEffect(() => {
      if (barObj.status === 'hello') return
      setBarObj(barObj => ({
        ...barObj,
        status: fooArr[1]
      })
    }, [fooArr]);
    

    With your updated query, you can use like:

    useEffect(() => {
      setBarObj(barObj => {
        const updatedStatus = barObj.status === 'hello' ? (barObj.status + 'world') : fooArr[1]
        return {
        ...barObj,
        status: updatedStatus
      }
    }, [fooArr]);