First off, let me say that I probably worded my question terribly… sorry.
I currently have a useEffect in my application that when you load my page it takes the data from my Firestore collection and sets it to an array to map on screen with a component. It works perfectly fine, however after about 10 minutes of running my application I receive the error "@firebase/firestore: Firestore (9.15.0): Uncaught Error in snapshot listener: FirebaseError: [code=resource-exhausted]: Quota exceeded.".
I added a console log and it looks like this is because my useEffect is constantly trying to read the data from the collection in firestore.
My question is, is there a way to only make this useEffect update the data / run when a new collection is added or deleted / modified?
Code:
import React, { useState, useEffect, useRef } from 'react';
import '../index.css';
import './Home.css';
import Note from '../components/Note';
import { useAuth } from '../contexts/AuthContext';
import { db } from '../firebase';
import { ReactComponent as Add } from '../imgs/add.svg';
import { doc, onSnapshot, query, collection } from 'firebase/firestore';
function Home() {
// Firebase states
const { currentUser } = useAuth();
const noteboardCollectionRef = collection(db, `users/${currentUser.uid}/noteboard-app`);
// useStates
const [notes, setNotes] = useState([]);
//useEffect
useEffect(()=>{
const q = query(noteboardCollectionRef)
const noteboardFirebase = onSnapshot(q, (querySnapshot)=>{
let noteArr = []
querySnapshot.forEach((doc)=>{
noteArr.push({...doc.data(), id: doc.id})
});
setNotes(noteArr);
console.log(notes)
})
return noteboardFirebase;
})
// Start of all functions
return (
<>
<div className='home-container'>
<div className='home-header flex'>
<h1 className='font-carter-one'>Noteboard</h1>
<div className='home-header-dark-container'>
<label className='font-carter-one'>Dark Mode</label>
<span className='home-header-dark-mode'>
<input type='checkbox' checked/>
<span className='dark-mode-slider pointer'/>
</span>
</div>
</div>
<div className='home-body flex-center-all'>
<div className='home-new-note flex-center-all flex-column pointer' onClick={()=>{setAddNoteModal(true)}}>
<Add className='pointer' id='new-note'/>
<h2 className='font-carter-one'>Add Note</h2>
</div>
{notes.map(((note, index) => <Note key={index} note={note} />))}
</div>
</div>
</>
)
}
export default Home;
Thank you in advanced!
3
Answers
You are facing this error because you dont have dependencies in the useEffect i.e
Because of which the useEffect runs every time the page is rendered , which is causing to make unlimited requests to the server which is leading to
quota exceeded error
in firebaseIf array is null i.e
[]
then it runs only the first time the page is rendered.If you want the useEffect to run only when the firestore is changed add dependency of
notes
i.e[notes]
.Now
useEffect
will run only when there is change innotes
!!Your final code should look like:
Add dependency to [] like this:
when dependency is changed, doSomething() will run again.
You can see detail in here!
So, as for your question you should edit code to this:
You could use onSnapshot() to make this happen something like this ;