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
);