skip to Main Content

I am learning React and learned some basics, so utilizing that knowledge by making this basic project.
I was making a Simple Notes Keeping Application using React and Firebase.

Data is perfectly transferred to the Firebase DataBase ✅.

fetching data ✅.

The problem I am facing is that the fetched data is not updating in UI.

import { useEffect, useState } from 'react';
import { AiFillCaretUp } from 'react-icons/ai';
import './Card.css';

export default function Card(props) {
  const [showPara, setShowPara] = useState(false);
  const [data, setData] = useState([]);
  console.log('inside card');

  useEffect(() => {
    let notesData = [];
    console.log('inside UseEffect');
    const fetchNote = async () => {
      const response = await fetch('https://notes-keeper-react-default-rtdb.firebaseio.com/notes.json');
      const data = await response.json();
      for (const key in data) {
        notesData.push({ id: key, title: data[key].title, note: data[key].note });
      }
    };
    fetchNote();
    // console.log(notesData);
    setData(notesData);
  }, []);

  const toggleHandler = () => {
    setShowPara((preVal) => !preVal);
  };

  const paraClass = showPara ? 'card-para toggle' : 'card-para';
  const rotate = showPara ? 'icon rotate' : 'icon';
  return (
    <div className='container'>
      {console.log('inside card container', data)}

      {data.map((card) => (
        <div className='card' key={card.id}>
          <div className='card-title' onClick={toggleHandler}>
            <h3>{card.title}</h3>
            <AiFillCaretUp className={rotate} />
          </div>
          <div className={paraClass}>
            <p>{card.note}</p>
          </div>
        </div>
      ))}
    </div>
  );
}

showing Data inside this

{console.log('inside card container', data)} 

But this is not Working

{data.map((card) => (
    <div className='card' key={card.id}>
      <div className='card-title' onClick={toggleHandler}>
        <h3>{card.title}</h3>
        <AiFillCaretUp className={rotate} />
      </div>
      <div className={paraClass}>
        <p>{card.note}</p>
      </div>
    </div>
  ))}
</div>

I hope you are understanding what is the problem.

2

Answers


  1. One way is to write it like this:

    useEffect(() => {
        let notesData = [];
        const fetchNote = async () => {
          const response = await fetch('https://notes-keeper-react-default-rtdb.firebaseio.com/notes.json');
          const data = await response.json();
          for (const key in data) {
            notesData.push({ id: key, title: data[key].title, note: data[key].note });
          }
          setData(notesData); // data is ready here
        };
        fetchNote();
      }, []);
    

    fetchNote is an async function so it takse some time to do its job and get the data. So you should wait until the data is ready and unfortunately the data is not ready when you use setData(notesData) right after calling fetchNote()

    Alternatively you can return the data inside async function and it automatically returns another promise that resolves to the data you want and there you can update your data:

    useEffect(() => {
        let notesData = [];
        const fetchNote = async () => {
          const response = await fetch('https://notes-keeper-react-default-rtdb.firebaseio.com/notes.json');
          const data = await response.json();
          for (const key in data) {
            notesData.push({ id: key, title: data[key].title, note: data[key].note });
          }
          return notesData; // returns a promise that resolves to 'notesData'
        };
    
        fetchNote()
          .then((updatedData) => {
            setData(updatedData);
          })
      }, []);
    
    Login or Signup to reply.
  2. fetchNote() is an asynchronous function, it returns a promise and you will have to wait until fetching the data. It will take some time to get the data from the database. Since you set the notesData immediately without waiting for the response using await keyword, it sets the empty array value to the data state.

    You can await for the fetchNote() before setting the data or you can set the data inside the fetchNote() function after for loop.

    const fetchNote = async () => {
          const response = await fetch('https://notes-keeper-react-default-rtdb.firebaseio.com/notes.json');
          const data = await response.json();
          for (const key in data) {
            notesData.push({ id: key, title: data[key].title, note: data[key].note });
          }
    
          //set the data here
          setData(notesData);
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search