rv7284
rv7284

Reputation: 1102

Firebase onSnapShot keeps calling

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

Answers (1)

Shababb Karim
Shababb Karim

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

Related Questions