Home > other >  React- Issue with infinite loop in useEffect
React- Issue with infinite loop in useEffect

Time:12-07

I have a useEffect() that fetches the data through axios, I want that to render only one time so I passed an array. Everything works fine, but the problem is whenever I try to sort the items, the second useEffect fires just followed by the first useEffect, which is causing the component to fetch the items all over again and again.

const [products, setProducts] = useState([]);

useEffect(() => {
    const getProducts = async () => {
      return await axios
        .get('/getAllProducts')
        .then((response) => {
          setProducts(response.data);
          console.log(products);
        })
        .catch((e) => {
          console.log(e);
        });
    };
    getProducts();
  }, [products]);

CodePudding user response:

This is because you passed an array containing your products state, rather than an empty array, which will fire useEffect on state change (for products state specifically). Try changing your code to an empty array:

useEffect(() => {
const getProducts = async () => {
  return await axios
    .get('/getAllProducts')
    .then((response) => {
      setProducts(response.data);
      console.log(products);
    })
    .catch((e) => {
      console.log(e);
    });
  };
  getProducts();
  }, []);

As @skyboyer mentioned below, it is good to note that state is not updated in a synchronous manner. Therefor, console.log(products) will not reflect an accurate value for your state when useEffect runs.

It is okay to use multiple useEffect hooks. If you would like to view your updated state in the console, or do some other work with it, you could add another useEffect hook and pass your state into the array:

useEffect(() => {
    console.log(products);
}, [products]);

CodePudding user response:

Since products is in the useEffect dependency array, it is going to run every time there are changes made to the products state. getProducts() runs setProducts which then in turn is going to trigger the use effect again. Using an empty array in the useEffect will tell it to only run when the component is mounted.

Like this:

useEffect(() => {
const getProducts = async () => {
  return await axios
    .get('/getAllProducts')
    .then((response) => {
      setProducts(response.data);
      console.log(products);
    })
    .catch((e) => {
      console.log(e);
    });
  };
  getProducts();
  }, []);
  • Related