Reputation: 1102
I'm new to React JS. Working on ToDo application with firebase.
import React, { useState, useEffect } from "react";
import "./App.css";
import ToDoInput from "./ToDoInput";
import db from "./firebase";
import ToDoItem from "./ToDoItem";
function App() {
const [toDos, setToDos] = useState([{ id: 1, task: "asd", status: false }]);
useEffect(() => {
console.log("User effect");
db.collection("ToDo")
.orderBy("createdAt")
.onSnapshot((snapshot) => {
setToDos(
snapshot.docs.map((doc) => ({
id: doc.id,
task: doc.data().task,
createdAt: doc.data().createdAt,
status: doc.data().status,
}))
);
});
});
return (
<div className="app">
<ToDoInput />
{toDos.map((toDo) => (
<ToDoItem
key={toDo.id}
task={toDo.task}
createdAt={toDo.createdAt}
status={toDo.status}
/>
))}
</div>
);
}
export default App;
In the above code onSnapshot funtion keeps firing same data and UI is in constant rendering.
And idea on how to solve this.
Upvotes: 1
Views: 489
Reputation: 3733
You need to pass an empty array argument in useEffect
. This way, the function will be called only the first time on component. Your code will run on component and also every time the state changes. Since you're changing state inside useEffect
, so you are stuck in a loop.
Do something like this:
useEffect(() => {
console.log("User effect");
db.collection("ToDo")
.orderBy("createdAt")
.onSnapshot((snapshot) => {
setToDos(
snapshot.docs.map((doc) => ({
id: doc.id,
task: doc.data().task,
createdAt: doc.data().createdAt,
status: doc.data().status,
}))
);
});
}, []);
Read more about it here on the notes.
Upvotes: 3