Reputation: 25
I am creating a simple agenda application that is hooked up to firebase as a backend. I want to fetch the data on every write and I am trying to dodge an infinite loop.
useEffect(() => {
const getTodos = () => {
console.log("I will run");
db.collection("Users")
.doc(user.email)
.collection("Todos")
.get()
.then((snapshot) => {
const loadedTodos = snapshot.docs.map((docs) => {
return {
todo: docs.data().todo,
isCompleted: docs.data().isCompleted,
id: docs.id,
};
});
setTodos(loadedTodos ?? []);
});
};
getTodos();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [todos]);
The initial todos state is null. However, when I fetch the firebase data, it changes and then causes a rerender on the component itself which causes another fetch again causing an infinite loop. I have broke the limit of the spark plan in firebase because of this and wasted days of work because of temporary blocks. I think this can be fixed with the useCallback hook, but I do not know how. Also, I want to add the same functionality with a chat application (where data will be written from two sides). Is it possible to rerender only when one of the two sides has written or does it have to be an infinite loop in such a case?
Upvotes: 0
Views: 141
Reputation: 25
I just added a new useState hook, shouldComponentRerender, that changes whenever a function of (addTodos, deleteTodo, setCompletionState) is called, and then the shouldComponentRerender state was added as a dependency for the useEffect hook. Gave me the result I wanted. Thanks!
Upvotes: 0
Reputation: 55613
The dependency you want in your effect is user.email
useEffect(() => {
const getTodos = () => {
console.log("I will run");
db.collection("Users")
.doc(user.email)
.collection("Todos")
.get()
.then((snapshot) => {
const loadedTodos = snapshot.docs.map((docs) => {
return {
todo: docs.data().todo,
isCompleted: docs.data().isCompleted,
id: docs.id,
};
});
setTodos(loadedTodos ?? []);
});
};
getTodos();
}, [user.email]);
You can read this as: every time user.email
changes, I will want to refetch the to-do list.
EDIT: The reason you are observing an infinite loop, as others have said, is because your effect's dependency gets changed by the effect itself, which causes the effect to run again. This can often be fixed by "lifting state up" - but in this case, it's because you're using the wrong dependency.
Upvotes: 2