Lili
Lili

Reputation: 47

Delete nested field in Firestore

I'm trying to delete a nested field in Firestore but I get FirebaseError: Function updateDoc() called with invalid data. deleteField() can only appear at the top level of your update data

So what I'm trying to delete is the individual fields (map) called bread, salt etc.

Picture of the firestore

const listRef = doc(db, "lists", list.id);
const onDismiss = useCallback(async (id: string) => {
    const onGoingIndex = onGoingItems.findIndex((item) => item.id === id);
    let getName = onGoingItems.find((item) => item.id === id)?.name || "";
 

    if (onGoingIndex !== -1) {
      onGoingItems.splice(onGoingIndex, 1);
    } else {
      const doneIndex = doneItems.findIndex((item) => item.id === id);
      getName = doneItems.find((item) => item.id === id)?.name || "";
      doneItems.splice(doneIndex, 1);
    }

    await updateDoc(listRef, {
      items: {
        [getName]: deleteField(),
      },
    });
  }, []);

I've also tried using FieldValue.delete() from firebase/firestore but it has no function called delete(). Error on fieldvalue

Any help would be appreciated!

Upvotes: 1

Views: 2407

Answers (2)

Aleksandar Nikolic
Aleksandar Nikolic

Reputation: 268

If you are using react-native-firebase you should probably call it like this firestore.FieldValue.delete(), based on the docs

The way to modify or delete a nested field is to generate a dot path like in the sample code.

const listRef = doc(db, "lists", list.id);
const onDismiss = useCallback(async (id: string) => {
    const onGoingIndex = onGoingItems.findIndex((item) => item.id === id);
    let getName = onGoingItems.find((item) => item.id === id)?.name || "";
 

    if (onGoingIndex !== -1) {
      onGoingItems.splice(onGoingIndex, 1);
    } else {
      const doneIndex = doneItems.findIndex((item) => item.id === id);
      getName = doneItems.find((item) => item.id === id)?.name || "";
      doneItems.splice(doneIndex, 1);
    }

    await updateDoc(listRef, {
      [`items.${getName}`]: firestore.FieldValue.delete()
    });
  }, []);

If you are using javascript SDK. For v9 of firebase you should import it like so

import { deleteField } from 'firebase/firestore';


  ...

  await updateDoc(listRef, {
    [`items.${getName}`]: deleteField(),
  });

Upvotes: 1

samthecodingman
samthecodingman

Reputation: 26196

Getting access to the "field delete" operation depends on which version of the Firebase SDKs you are using:

  • For v8 and older (or the v9 compatibility mode), you use firebase.firestore.FieldValue.delete().
  • For v9 and newer, you use deleteField() (as in your case)
  • For react-native-firebase, you currently use firestore.FieldValue.delete() (based on the docs, as pointed out by @AlekssandarNikolic in their answer).

The reason you can't use FieldValue.delete() is because it was removed in v9 of the SDK in favour of deleteField().

However, as that error tells you, a "delete field" marker can only appear at the top level of your update data. This is because of the way Firestore handles updating fields that are in nested objects to prevent the wrong data from being deleted.

With the code as you have written it, and getName was "Bread", you would be updating the entire items object to { Bread: <deleteMe> }, which would also delete "Salt".

await updateDoc(listRef, {
  items: {
    [getName]: deleteField(),
  },
});

To correct this, use dot notation of the field you want to mutate (which will correctly leave the other nested fields alone):

await updateDoc(listRef, {
  [`items.${getName}`]: deleteField()
});

See updating nested fields (and deleting fields) for more information.

Upvotes: 6

Related Questions