0

I'm building a CRUD application using redux toolkit and firestore, and I cannot figure out how to delete an item from firestore, and I really don't know why the following code isn't working. I've tried this in several different ways, and the current error that I'm getting is:

"Cannot use 'in' operator to search for '_delegate' in undefined"

Here's the relevant code from the slice:

export const recipeSlice = createSlice({
    name: 'recipesSlice',
    initialState: {
        recipes: []
        
    },
    reducers: {
        ADD_RECIPE: (state, action) => {
            state.recipes.push(action.payload)
        },
        DELETE_RECIPE: (state, action) => {
            state.recipes = state.recipes.filter((recipe) => recipe.recipeId !== action.payload.recipeId)
        }

And here is the thunk that I cannot, for the life of me make work:


export const deleteRecipe = ({recipeId}) => {
        return async (dispatch) => {
            const q = query(collection(db, "recipes"), where("recipeId", "==", `${recipeId}`));
            const querySnapshot = await getDocs(q);
            querySnapshot.forEach(async(doc) => {
                console.log(doc.id, " => ", doc.data())
                await deleteDoc(doc)
            });
            dispatch(DELETE_RECIPE({recipeId}))
        }
}

I didn't use createAsyncThunk because it didn't seem to be a good use case, but I could be wrong.

I've tried firing this function with hard-coded dummy data, and that doesn't help. I have also tried running this code without the 'DELETE_RECIPE' reducer but that doesn't make a difference. I thought that using async/await within the forEach loop on the querySnapshot would work because it's not a typical forEach loop but rather a method in Firestore to iterate over querysnapshot.

JordanK
  • 65
  • 1
  • 5
  • 2
    Sorry, but there's a lot going on here that we can't readily see, so I recommend spending some time on [creating a minimal repro](http://stackoverflow.com/help/mcve). For example: if you just run the code that creates `docRef` (with a hardcoded recipe ID) and then call `deleteDoc` with that, does it delete the document? If so, the problem has likely nothing to do with Firestore, but is more likely in how you pass the information to `deleteRecipe`. – Frank van Puffelen Jul 10 '22 at 21:21
  • Hi, I just refactored and edited - hope it's a bit clearer! – JordanK Jul 11 '22 at 05:26
  • The `deleteDoc()` takes a `DocumentReference` as parameter and not the `DocumentSnapshot` itself. Also instead of using an `async` function in `forEach`, try using [`Promise.all()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all). Can you try the code in this [gist](https://gist.github.com/DharmarajX24/f3e05d31a8e195a65b97e44e2ee1008f) ? – Dharmaraj Jul 11 '22 at 05:35
  • 1
    Good point Dharmaraj: that call should be ` deleteDoc(doc.ref)`. Also note that the `await` you use on that line won't do anything, as you can't use `await` meaningfully in a `forEach` (see [here](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop) for more). – Frank van Puffelen Jul 11 '22 at 14:24
  • Hi Dharmaraj, the code in that gist does work, thank you! – JordanK Jul 11 '22 at 15:38
  • 1
    Hi @Dharmaraj, can you post your comment as an answer? Thank you. – Chanpols Jul 13 '22 at 00:11

1 Answers1

1

The deleteDoc() functions takes DocumentReference of the document and not the snapshot. Also try using Promise.all() or Batched Writes to delete the documents at once instead of using a forEach() loop. Try refactoring the code as shown below:

const querySnapshot = await getDocs(q);

const deletePromises = querySnapshot.docs.map((d) => deleteDoc(d.ref))

await Promise.all(deletePromises)

console.log("Documents deleted")
Dharmaraj
  • 47,845
  • 8
  • 52
  • 84