TransWikia.com

useEffect infinite loop when getting data from database

Stack Overflow Asked by Leo S on January 18, 2021

In my project, for sending a request for getting my user data and show them. I wrote the above code but i realised that if i pass the "people" to useEffect’s dependency (second parameter) react sends infinite request to my firebase but if i delete and keep the second parameter empty the useEffect works correct what is the difference between these two?

Here is the code that goes to infinite loop:

const [people, setPeople]=useState([])

useEffect(() => {
    const unsubscribe=database.collection("people").onSnapshot(snapshot=>
        setPeople(snapshot.docs.map(doc=>doc.data()))
        )
        

    return () => {
        unsubscribe()
    }
}, [people]) // if i change the second parameter with an empty list this problem solved.

return (
    <div>
        <h1>TinderCards</h1>
        <div className="tinderCards_cardContainer">
        {people.map(person =>
           <TinderCard
            className="swipe"
            key={person.name}
            preventSwipe={["up","down"]}
           >
            <div style={{backgroundImage: `url(${person.url})`}} className="card">
                <h3>{person.name}</h3>

            </div>
            </TinderCard> 
            )}
        </div>

    </div>
)

4 Answers

PROBLEM

useEffect runs every time when any one of values given to dependency array changes. Since, you're updating your people after the db call. The reference to array people changes, hence triggering an infinite loop on useEffect

SOLUTION

You do not need to put people in the dependency array. Your useEffect function doesn't depend on people.

useEffect(() => {
    const unsubscribe=database.collection("people").onSnapshot(snapshot=>
        setPeople(snapshot.docs.map(doc=>doc.data()))
        )
        

    return () => {
        unsubscribe()
    }
}, [])

Correct answer by Prateek Thapa on January 18, 2021

main problem is that the people array which is being created at every set-call is not the same. The object is completely different. I also had this trouble as i want to display the contents as soon as the some new "people" is added to the database from the admin panel, but it turns out that without refreshing this thing cannot be solved otherwise u can make your own hook with PROPER comparisons .

Maybe u can try by comparing the length of the PEOPLE array. I haven't tried it yet but i think it will work.

Answered by hopper01 on January 18, 2021

Essentially, the useEffect hook runs the inner function code every time any of the dependencies in the dependency array (second parameter) change.

Since setPeople changes people, the effect keeps running in an infinite loop:

useEffect(() => {
  ... setPeople() ... // <- people changed
}, [people]);         // <- run every time people changes

If you needed somehow the value of people and you need to have it in the dependency array, one way to check is if people is not defined:

useEffect(() => {
  if (!people) {
    // ... do something
    setPeople(something);
  }
}, [people]);

As you correctly pointed out, simply taking off the people dependency tells the effect to only run once, when the component is "mounted".

On an extra note, you may be wondering why people is changing if you are fetching the same exact results. This is because the comparison is shallow, and every time an array is created, it's a different object:

const a = [1,2,3];
const b = [1,2,3];

console.log(a === b); // <- false

You would need to do deep equality checks for that.

Answered by Yuan-Hao Chiang on January 18, 2021

The issue is after you set state in useEffect, the people value will be changed which will trigger another useEffect call hence an infinite loop.

You can modify it to this:-

useEffect(() => {
    const unsubscribe=database.collection("people").onSnapshot(snapshot=>
        setPeople(snapshot.docs.map(doc=>doc.data()))
        )
        

    return () => {
        unsubscribe()
    }
}, [])

Answered by maya_nk99 on January 18, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP