tqf
Version:
React Query hooks for Firebase.
239 lines (198 loc) • 6.08 kB
text/mdx
---
title: Data Mutation | Firestore
description: Hooks for integrating with Firestore.
---
This page information on how you can mutate data on Firestore, such as
updating and deleting, or running transactions and write batches.
All hooks are built upon the [`useMutation`](https://react-query.tanstack.com/reference/useMutation)
hook, making it super simple to handle loading states, success and errors.
To add a document to a collection, use the `useFirestoreCollectionMutation` hook.
It accepts a `CollectionReference` and when the mutation is triggered, the provided
data is added as a new document.
```jsx
import { useFirestoreCollectionMutation } from "@react-query-firebase/firestore";
import { collection } from "firebase/firestore";
import { firestore } from "./firebase";
function AddDocument() {
const ref = collection(firestore, "products");
const mutation = useFirestoreCollectionMutation(ref);
return (
<>
<button
disabled={mutation.isLoading}
onClick={() => {
mutation.mutate({
name: "New product!",
price: 10,
});
}}
>
Add document
</button>
{mutation.isError && <p>{mutation.error.message}</p>}
</>
);
}
```
If you need to set or update the data on an existing document, use
the `useFirestoreDocumentMutation` hook.
```jsx
import { collection, doc } from "firebase/firestore";
import { useFirestoreDocumentMutation } from "@react-query-firebase/firestore";
import { firestore } from "./firebase";
function SetDocument() {
const collection = collection(firestore, "products");
const ref = doc(collection, "123");
const mutation = useFirestoreDocumentMutation(ref);
return (
<>
<button
disabled={mutation.isLoading}
onClick={() => {
mutation.mutate({
name: "New product!",
price: 20,
});
}}
>
Set document
</button>
{mutation.isError && <p>{mutation.error.message}</p>}
</>
);
}
```
In this example, the document will be overwritten with the provided data.
You can optionally pass [`SetOptions`](https://firebase.google.com/docs/reference/js/firestore_.md#setoptions)
to indiciate you wish to merge data instead:
```js
const mutation = useFirestoreDocumentMutation(ref, {
merge: true,
});
```
To delete a document from your collection, use the `useFirestoreDocumentDeletion` hook.
```jsx
import { collection, doc } from "firebase/firestore";
import { useFirestoreDocumentDeletion } from "@react-query-firebase/firestore";
import { firestore } from "./firebase";
function DeleteDocument() {
const collection = collection(firestore, "products");
const ref = doc(collection, "456");
const mutation = useFirestoreDocumentDeletion(ref);
return (
<>
<button
disabled={mutation.isLoading}
onClick={() => {
mutation.mutate();
}}
>
Delete document
</button>
{mutation.isError && <p>{mutation.error.message}</p>}
</>
);
}
```
To run a transaction, use the `useFirestoreTransaction` hook. The hook
allows you to define the transaction function and execute it when ready.
```jsx
import { collection, doc } from "firebase/firestore";
import { useFirestoreTransaction } from "@react-query-firebase/firestore";
import { firestore } from "./firebase";
function LikeButton() {
const collection = collection(firestore, "products");
const ref = doc(collection, "123");
const mutation = useFirestoreTransaction(ref, async (tsx) => {
// Get the document
const doc = await tsx.get(ref);
const newLikes = doc.data().likes + 1;
// Increase the `likes` count
tsx.update(ref, {
likes: newLikes,
});
return newLikes;
});
return (
<>
<button
disabled={mutation.isLoading}
onClick={() => {
mutation.mutate();
}}
>
Like!
</button>
{mutation.isError && <p>{mutation.error.message}</p>}
</>
);
}
```
To learn more about transactions, read the [Firestore guide](https://firebase.google.com/docs/firestore/manage-data/transactions#transactions).
To execute many updates at once, use the `useFirestoreWriteBatch` hook.
Provide the hook with a `WriteBatch` instance, add batches writes and commit
the batch with the mutation trigger.
```jsx
import { writeBatch, collection, doc } from "firebase/firestore";
import { useFirestoreWriteBatch } from "@react-query-firebase/firestore";
import { firestore } from "./firebase";
function WriteBatchDocuments() {
// Define the WriteBatch instance
const batch = writeBatch(firestore);
const ref = doc(collection(firestore, "products"), "123");
const mutation = useFirestoreWriteBatch(batch);
return (
<>
{/* Update the WriteBatch instance */}
<button onClick={() => batch.delete(ref)}>Stage Deletion</button>
{/* Commit the write batch */}
<button
disabled={mutation.isLoading}
onClick={() => {
mutation.mutate();
}}
>
Like!
</button>
{mutation.isError && <p>{mutation.error.message}</p>}
</>
);
}
```
All mutation hooks are built on-top of the [`useMutation`](https://react-query.tanstack.com/reference/useMutation) hook,
and allow you define mutation side effects:
```js
const mutation = useFirestoreCollectionMutation(ref, {
onSuccess() {
toast.success("Document added!");
},
onError(error) {
toast.error("Failed to add document!");
},
onMutate() {
toast.info("Adding document...");
},
});
// or on the mutation function!
mutation.mutate(
{ name: "New Product!" },
{
onSuccess() {
toast.success("Document added!");
},
onError(error) {
toast.error("Failed to add document!");
},
onMutate() {
toast.info("Adding document...");
},
}
);
```