UNPKG

tqf

Version:

React Query hooks for Firebase.

239 lines (198 loc) 6.08 kB
--- title: Data Mutation | Firestore description: Hooks for integrating with Firestore. --- # Data Mutation 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. ## Adding a document to a collection 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>} </> ); } ``` ## Setting / Updating a document 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, }); ``` ## Deleting a document 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>} </> ); } ``` ## Running Transactions 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). ## Write Batches 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>} </> ); } ``` ## Side Effects 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..."); }, } ); ```