Home > Software engineering >  Why is this reactjs useEffect function running endlessly?
Why is this reactjs useEffect function running endlessly?

Time:05-04

Here is a useEffect hook that I used in reactjs:

Problem: The useEffect calls fetchAllCategories() endlessly. Infact, over 1000 requests until I terminate. I only want it to run on page mount and when I click on the button to change catName state. What could I be doing wrong?

  const [catName, setCategories] = useState([]);

  const categoryRef = useRef();

useEffect(()=>{
   
         const fetchAllCategories = async () =>{
        try{
            const res = await axios.get(`${BASE_URL}/category`)
        return setCategories(res.data);
       
        
        }catch(err){

        }

        
    }

    fetchAllCategories()
    
   
}, [catName])


 //create new category

const createNewCategory = async ()=>{
    const categoryName = {
        catName: categoryRef.current.value
    }
    try{
        const response = await axiosPrivate.post(`${BASE_URL}/category`, categoryName, { withCredentials: true,
        headers:{authorization: `Bearer ${auth}`}
        })
        return setCategories([response.data])
        
    }catch(err){

    }
    
  }

The button that triggers changes in catName

<button onClick={ createNewCategory} className='button-general'>Create</button>

CodePudding user response:

You trigger the effect to be run on change of catNames, and then change catNames from the effect itself. This results in the endless self-triggering of the effect.

One solution could be to make your effect depend on nothing:

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

CodePudding user response:

Thank you all for pointing out the issue to me. Since I now know the issue, I have been able to fix it. All I did was create another state and made the useEffect to depend on it. Then, whenever the button is clicked, I change the state to the opposite of the initial state. This works and doesnt cause endless calls.

CodePudding user response:

If you absolutely need catName as a dependency, this can work for you:

useEffect(() => {
    const fetchAllCategories = async () => {
        try {
            const res = await axios.get(`${BASE_URL}/category`);
            return setCategories(res.data);
        } catch (err) {}
    };

    fetchAllCategories();
}, [JSON.stringify(catName)]);

CodePudding user response:

This is happening because you update the catName state inside the useEffect using setCategories(res.data) this keeps triggering your useEffect thus an infinite loop

CodePudding user response:

You programmed it to run endlessly.

REASON

See, this React hook useEffect has two parameters:

  1. Effect, the callback function which is called whenever the component renders.

  2. List of Dependencies on which the useEffect hook depends and re-renders if any such dependency is updated.

Now, in your case, you've passed catName as a dependency, whose state is updated when the button is clicked. This causes useEffect to call the callback function which calls fetchAllCategories() which also update catName. And this causes an endless loop.

SOLUTION

Just remove the dependency from useEffect as:

useEffect(() {
    ...
}, []);

Now, updating catName won't cause the effect (The Callback function) to be called endlessly.

  • Related