Satrim
Satrim

Reputation: 13

problem with infinite loop in function hook useEffect

I have a problem with an infinite loop on my hook, I'm passing the data of the local JSON breakfast. If you are iterating with map the data and I am taking it to paint a menu of buttons. If I remove the data at the end of the function, and leave the empty array, it sends me the following error:

const BreakfastComponent = () => {

   const breakfast = [
    {
      id: 0,
      name: "Sandwich de jamón y queso",
      price: '35',
      img: "https://i.ibb.co/ynC9xHZ/sandjc.png",

    },
    {
      id: 1,
      name: "Jugo Natural",
      price: '15',
      img: "https://i.ibb.co/8mrd4MK/orangejuice.png",
    },
    {
      id: 2,
      name: "Café americano",
      price: '20',
      img: "https://i.ibb.co/nsj1GL0/americancoffe.png",
    },
    {
      id: 3,
      name: "Café con leche",
      price: '28',
      img: "https://i.ibb.co/GRPBm7j/coffeandmilk.png",
    }
  ];


  const [stateProduct, setStateProduct] = useState([ ]);


  useEffect(() => {

    setStateProduct(breakfast);
  }, [breakfast]);

  return (

      <section className="databreakfast">
        {stateProduct.map((element, item) =>
          <ButtonsBComponent
            key={item}
            {...element}

          />
        )}
        </section>



  )
};

export default BreakfastComponent;

React Hook useEffect has a missing dependency: 'breakfast'. Either include it or remove the dependency array react-hooks/exhaustive-deps

Upvotes: 1

Views: 3961

Answers (2)

Shubham Khatri
Shubham Khatri

Reputation: 282140

The problem is simple, you have breakfast array as a dependency to useEffect and in useEffect you are setting the breakfast array itself. Now since the const breakfast array is declared inside the component, a new reference to it is generated everytime and since useEffect sets the array in state, it re-renders and on next re-render the comparison for breakfast array fails since the reference has changed.

The solution is simple, you don't need to have the const array in the component and also you don't need to use useEffect

const breakfast = [
    {
      id: 0,
      name: "Sandwich de jamón y queso",
      price: '35',
      img: "https://i.ibb.co/ynC9xHZ/sandjc.png",

    },
    {
      id: 1,
      name: "Jugo Natural",
      price: '15',
      img: "https://i.ibb.co/8mrd4MK/orangejuice.png",
    },
    {
      id: 2,
      name: "Café americano",
      price: '20',
      img: "https://i.ibb.co/nsj1GL0/americancoffe.png",
    },
    {
      id: 3,
      name: "Café con leche",
      price: '28',
      img: "https://i.ibb.co/GRPBm7j/coffeandmilk.png",
    }
  ];

const BreakfastComponent = () => {

  const [stateProduct, setStateProduct] = useState(breakfast);


  return (

      <section className="databreakfast">
        {stateProduct.map((element, item) =>
          <ButtonsBComponent
            key={item}
            {...element}

          />
        )}
        </section>



  )
};

export default BreakfastComponent;

Upvotes: 1

larz
larz

Reputation: 5766

useEffect's second argument is an array of state/hooks to be watched and when they change, to run the effect. Since your breakfast is a const, I'm guessing you just want the original stateProduct to be breakfast. So instead of using [] as the default, use breakfast.

const [stateProduct, setStateProduct] = useState(breakfast);

Also, probably a good idea to declare const breakfast ... outside of your react functional component so it doesn't re-declare it on every re-render.

Upvotes: 1

Related Questions