0

Here is the code to initialize categoryArray. I want to run the useEffect only if the categoryArray data changes.

const [categoryArray, setCategoryArray] = useState([]);

useEffect(() => {
        axios.get('http://localhost:8080/user/category')
            .then(response => {
                
                if (categoryArray !== response.data.category) {
               
                    setCategoryArray(response.data.category);
                }
            })
            .catch(err => {
                console.log(err);
            })

    }, [categoryArray])


I tried to apply a conditional statement to setCategoryArray only if there is some change but somehow that conditional statement is not working properly and an infinite loop is happening.

Could you please guide me on where I am getting wrong, also let me know if more information is required.

Pawan
  • 459
  • 5
  • 17
  • 1
    `[]==[]` is false, newly created array never equal anything, so `categoryArray !== response.data.category` always true, so changed->effect->ajax->set->changed.... – Josh Lin Apr 15 '22 at 09:05

3 Answers3

0

The last parameter of a useEffect marks on what value changes the useEffect should be triggered again.

Since you're setting categoryArray with the value of the axios call, but also configured the useEffect to be triggered when that variable changes, it will trigger again and again.


You probably can just remove the [categoryArray] so the useEffect is only triggered once on the initial render.

0stone0
  • 34,288
  • 4
  • 39
  • 64
0

as can be seen in your code you have categoryArray in dependency array , and inside useEffect callback you are updating it,which cause it to generate infinite loop,if you need to load data only one time you just need to remove it from dependency,like

useEffect(() => {

    axios.get('http://localhost:8080/user/category')
        .then(response => {
            
            //if (categoryArray !== response.data.category) {
           
                setCategoryArray(response.data.category);
            //}
        })
        .catch(err => {
            console.log(err);
        })

}, [])

or you can inside callback make sure that api call only executed if categoryArray.length==0,like this

useEffect(() => {
    if(categoryArray.length>0)return;
    axios.get('http://localhost:8080/user/category')
        .then(response => {
            
            //if (categoryArray !== response.data.category) {
           
                setCategoryArray(response.data.category);
            //}
        })
        .catch(err => {
            console.log(err);
        })

}, [categoryArray])

this way it will only make api call when array is empty

Jatin Parmar
  • 2,759
  • 5
  • 20
  • 31
0
useEffect(() => {
        axios.get('http://localhost:8080/user/category')
            .then(response => {
                
                console.log("array: "+ response.data.category);
                
                if (JSON.stringify(categoryArray) !== JSON.stringify(response.data.category)) {
                    
                    setCategoryArray(response.data.category);
                }
            })
            .catch(err => {
                console.log(err);
            })

   })

By changing if (categoryArray !== response.data.category) to this if (JSON.stringify(categoryArray) !== JSON.stringify(response.data.category)) and by removing [categoryArray] from useEffect(()=>{.............},[categoryArray]) my code started to work fine and the infinite loops were handled by the conditional statement.

In my previous code, I found that even though categoryArray and response.data.category had the same value the code inside the conditional block was not executing so I searched different methods to compare arrays in javascript then I came across JSON.stringify().

I didn't come across a proper explanation on why only === didn't work when comparing arrays in my case. If someone knows a reason why JSON.stringify() worked then please write the explanation so that it could be helpful to others.

Pawan
  • 459
  • 5
  • 17