Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

156
Views
How to make useEffect rerender after the data is changed?

I want the useEffect to fetch and render rooms data. And rerender the data when the new room is being added to rooms

Code to fetch data and display data with useEffect and an empty dependency.

const [rooms, setRooms] = useState([]);

  const getRoomsData = async () => {
    const querySnapshot = await getDocs(collection(db, "rooms"));
    const data = querySnapshot.docs.map((doc) => ({
      id: doc.id,
      data: doc.data(),
    }));

    setRooms(data);
  };

  useEffect(() => {
    getRoomsData();
    console.log("rerendered");
  }, []);

With this code, after I added new room to rooms. I need to manually refresh the page to see the new data rendered. What should I do to make it rerender itself after new "room" is added to rooms?

Code to add room:

    const roomName = prompt("please enter name for chat room");

    if (roomName) {
      addDoc(collection(db, "rooms"), {
        name: roomName,
      });
    }
  };

I tried adding rooms to the useEffect dependency, which has the result I want (no need to refresh), but it is only because it is rendering infinitely, which is bad. What is the proper way of doing it?

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

You are getting infinite re-renders because the function inside the useEffect is updating the state of rooms which is in the dependency array of the effect. This will always cause infinite re-renders.

To answer your question verbatim: "How do I make it rerender only when the data is changed?"

Since rooms and data are set to be the same, you can keep your useEffect how it is, but then create another useEffect to fire only when the component mounts to call getRoomsData().

const [rooms, setRooms] = useState([]);

  const getRoomsData = async () => {
    const querySnapshot = await getDocs(collection(db, "rooms"));
    const data = querySnapshot.docs.map((doc) => ({
      id: doc.id,
      data: doc.data(),
    }));

    setRooms(data);
  };

  useEffect(() = > {
    getRoomsData();
  }, [])

  useEffect(() => {
    console.log("rerendered");
  }, [rooms]);

I think the real crux of solving your issue is knowing when to call getRoomsData(), because depending on that, you will change the useEffect dependency array to fit that need.

about 4 years ago · Juan Pablo Isaza Report

0

I can think of two approaches to solving this problem, without having to use useEffect, the first one being a workaround where you update the rooms state locally without having to fetch it from the server, i.e, you are basically constructing and appending an object to the existing array of rooms, this is possible only if you know the structure of the object, looking at your getRoomsData function, it seems that you are returning a data array with each item having the following object structure.

{
 id: <DOCUMENT_ID>,
 data: {
  name: <ROOM_NAME>
 }
}

So, when you add a room, you can do something like this:

   const roomName = prompt("please enter name for chat room");

    if (roomName) {
      addDoc(collection(db, "rooms"), {
        name: roomName,
      });
      let newRoom = {
        id: Math.random(), //random id
        data: {
          name: roomName
        }
      }
      setRooms([...rooms,newRoom])
  };

This way, you can also reduce the number of network calls, which is a performance bonus, but the only downside is that you've to be sure about the object structure so that the results are painted accordingly.
In case, you are not sure of the object structure, what you could do is instead invoke getRoomsData after you add your new room to the collection, like so:

   const roomName = prompt("please enter name for chat room");

    if (roomName) {
      addDoc(collection(db, "rooms"), {
        name: roomName,
      }).then(res=>{
          getRoomsData();
      })
  };

This is would ensure to fetch the latest data (incl. the recently added room) and render your component with all the results. In either of the methods you follow, you could use your useEffect only once when the component mounts with an empty dependency array.

 useEffect(() => {
    getRoomsData();
    //console.log("rerendered");
  }, []);

By doing this, you first basically display the data when the user visits this page for the first time/when the components mount for the first time. On subsequent additions, you can either append the newly added room as an object to the rooms array after adding it to the database or add it to the database and fetch all the results again, so that the latest addition is rendered on the screen.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!