简体   繁体   中英

Add new fields as an array in the same document without override the old ones in Firestore using React

I'm trying to add new fields in a document that related to the logged in user (same UID) to create a new document with the same UID as the user's UID I use the following:

const collectionRef = collection(db, 'data');

// submit function to add data
const handleSubmit = async (e) => {
    e.preventDefault();
    onAuthStateChanged(auth, async (user) => {
        const uid = user.uid;
        try {
            // overrides the data
            await setDoc(doc(collectionRef, uid), {
                food: food,
                quantity: quantity,
            })

            alert("Data added successfully")
        } catch (error) {
            alert(`Data was not added, ${error.message}`)
        }
    }, [])
}

For add more fields to the array, I use the following:

const collectionRef = collection(db, 'data');

// submit function to add data
const handleSubmit = async (e) => {
    e.preventDefault();
    onAuthStateChanged(auth, async (user) => {
        const uid = user.uid;
        try {
            await updateDoc(doc(collectionRef, uid), {
                food: arrayUnion(food),
                quantity: arrayUnion(quantity),
            })
            
            alert("Data added successfully")
        } catch (error) {
            alert(`Data was now added, ${error.message}`)
        }
    }, [])
}

the complete code:

const collectionRef = collection(db, 'data');

const handleSubmit = async (e) => {
    e.preventDefault();
    onAuthStateChanged(auth, async (user) => {
        const uid = user.uid;
        try {
            // overrides the data - ???
            await setDoc(doc(collectionRef, uid), {
                food: food,
                quantity: quantity,
            })
       
            // add more fields to the array
            await updateDoc(doc(collectionRef, uid), {
                food: arrayUnion(food),
                quantity: arrayUnion(quantity),
            })

            alert("Data added successfully")
        } catch (error) {
            alert(`Data was now added, ${error.message}`)
        }
    }, [])
}

I can add more fields with the updateDoc() function, but if I will not comment or delete the setDoc() function after creating the new document, it will override the fields inside the document.

screenshot of the DB (Firestore): I can add more fields only if I comment the setDoc() function after the doc first created

Firestore

The onAuthStateChanged() observer runs every time the user's auth state changes and then the set() will overwrite the existing document removing any existing data. You can try using merge option that won't delete rest of the fields as shown below:

const docRef = doc(db, 'users', user.uid)

await setDoc(docRef, { food, quantity }, { merge: true })

This will still however overwrite the 'food' and 'quantity' arrays with the new value that you provide. So it might be best to use setDoc() only once after users registers in your application and use updateDoc thereafter.


Alternatively, you can also unsubscribe from the listener as shown below:

const handleSubmit = async (e) => {
  e.preventDefault();
  const unsub = onAuthStateChanged(auth, async (user) => {
    // process data
    unsub();
  })
}

The handler might still trigger again if auth state changes before your processing is complete. You should use onAuthStateChanged() when the web app loads for the first time and then redirect user to different pages based on their auth state. Once you confirm that user is logged in then you can simply use the following to get current user:

const user = auth.currentUser; 

if (user) {
  // update document. 
}

If you want to create-or-update the document, you can use { merge: true } :

await setDoc(doc(collectionRef, uid), {
    food: food,
    quantity: quantity,
}, { merge: true }) // 👈

Also see the second code snippet in the documentation on setting a documents .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM