Home > database >  useEffect runs forever
useEffect runs forever

Time:03-18

I am a newbie to React.js. I have a question about useEffect today. I know that if I pass an empty [] as a second parameter, useEffect only runs once. But, my app runs too often and if I console.log(something), I can see that. Here is my code. Please look at line 19. [] is there. I tried to add quizzes in [] like [quizzes].

import { useEffect, useState } from 'react';
import { doc, collection, onSnapshot } from 'firebase/firestore';

import db from '../firebaseConfig';

const Quiz = () => {
  const [quizes, setQuizes] = useState([]);
  useEffect(() => {
    const collectionRef = collection(db, 'quizes');
    const unsub = onSnapshot(
      collectionRef,
      snapshot => {
        setQuizes(
          snapshot.docs.map(
            doc => ({ ...doc.data(), id: doc.id })
          )
        );
      },
      []
    );
    return unsub;
    // getData(): run once
    // onSnapshot(): listen for realtime updates
  });

  console.log(quizes)

  return (
    <div className='quiz'>
      {quizes.map(quiz => (
        <div key={quiz.id} className='quiz'>
          {quiz.correctAns}
        </div>
      ))}
    </div>
  );
};

export default Quiz;

CodePudding user response:

You have a typo where you have misplaced the empty array and passed it into the onSnapshot() call instead of the useEffect() call.

In addition, you should make sure that you attach listeners to both of the onSnapshot's events - next and error. When you don't use an observer object like shown below, these are the second and third arguments to the onSnapshot call.

// the recommended onSnapshot form in React
const unsub = onSnapshot(
  ref,
  {
    next: (snapshot) => { /* ... */ },
    error: (err) => { /* ... */ }
  }
);
// OR, the more confusing as your handlers grow in size:
const unsub = onSnapshot(
  ref,
  (snapshot) => { /* ... */ },
  (err) => { /* ... */ }
);
useEffect(
  () => {
    const collectionRef = collection(db, 'quizes');
    const unsub = onSnapshot(
      collectionRef,
      {
        next: (snapshot) => {
          setQuizes(
            snapshot.docs.map(
              doc => ({ ...doc.data(), id: doc.id })
            )
          );
        },
        error: (err) => {
          // don't forget error handling! e.g. update component with an error message
          console.error("quizes listener failed: ", err);
        }
      }
    ); // <-- not here
    return unsub;
    // getData(): run once
    // onSnapshot(): listen for realtime updates
  },
  [] // <-- empty array goes here, not in onSnapshot
);
  • Related