UNPKG

@apollo/client

Version:

A fully-featured caching GraphQL client.

158 lines (157 loc) 5.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useMutation = useMutation; const tslib_1 = require("tslib"); const equality_1 = require("@wry/equality"); const React = tslib_1.__importStar(require("react")); const internal_1 = require("@apollo/client/utilities/internal"); const useIsomorphicLayoutEffect_js_1 = require("./internal/useIsomorphicLayoutEffect.cjs"); const useApolloClient_js_1 = require("./useApolloClient.cjs"); /** * > Refer to the [Mutations](https://www.apollographql.com/docs/react/data/mutations/) section for a more in-depth overview of `useMutation`. * * @example * * ```jsx * import { gql, useMutation } from "@apollo/client"; * * const ADD_TODO = gql` * mutation AddTodo($type: String!) { * addTodo(type: $type) { * id * type * } * } * `; * * function AddTodo() { * let input; * const [addTodo, { data }] = useMutation(ADD_TODO); * * return ( * <div> * <form * onSubmit={(e) => { * e.preventDefault(); * addTodo({ variables: { type: input.value } }); * input.value = ""; * }} * > * <input * ref={(node) => { * input = node; * }} * /> * <button type="submit">Add Todo</button> * </form> * </div> * ); * } * ``` * * @param mutation - A GraphQL mutation document parsed into an AST by `gql`. * @param options - Options to control how the mutation is executed. * @returns A tuple in the form of `[mutate, result]` */ function useMutation(mutation, options) { const client = (0, useApolloClient_js_1.useApolloClient)(options?.client); const [result, setResult] = React.useState(() => createInitialResult(client)); const ref = React.useRef({ result, mutationId: 0, isMounted: true, client, mutation, options, }); (0, useIsomorphicLayoutEffect_js_1.useIsomorphicLayoutEffect)(() => { Object.assign(ref.current, { client, options, mutation }); }); const execute = React.useCallback((executeOptions = {}) => { const { options, mutation } = ref.current; const baseOptions = { ...options, mutation }; const client = executeOptions.client || ref.current.client; if (!ref.current.result.loading && ref.current.isMounted) { setResult((ref.current.result = { loading: true, error: undefined, data: undefined, called: true, client, })); } const mutationId = ++ref.current.mutationId; const clientOptions = (0, internal_1.mergeOptions)(baseOptions, executeOptions); return (0, internal_1.preventUnhandledRejection)(client .mutate(clientOptions) .then((response) => { const { data, error } = response; const onError = executeOptions.onError || ref.current.options?.onError; if (error && onError) { onError(error, clientOptions); } if (mutationId === ref.current.mutationId) { const result = { called: true, loading: false, data, error, client, }; if (ref.current.isMounted && !(0, equality_1.equal)(ref.current.result, result)) { setResult((ref.current.result = result)); } } const onCompleted = executeOptions.onCompleted || ref.current.options?.onCompleted; if (!error) { onCompleted?.(response.data, clientOptions); } return response; }, (error) => { if (mutationId === ref.current.mutationId && ref.current.isMounted) { const result = { loading: false, error, data: void 0, called: true, client, }; if (!(0, equality_1.equal)(ref.current.result, result)) { setResult((ref.current.result = result)); } } const onError = executeOptions.onError || ref.current.options?.onError; if (onError) { onError(error, clientOptions); } throw error; })); }, []); const reset = React.useCallback(() => { if (ref.current.isMounted) { const result = createInitialResult(ref.current.client); Object.assign(ref.current, { mutationId: 0, result }); setResult(result); } }, []); React.useEffect(() => { const current = ref.current; current.isMounted = true; return () => { current.isMounted = false; }; }, []); return [execute, { reset, ...result }]; } function createInitialResult(client) { return { data: undefined, error: undefined, called: false, loading: false, client, }; } //# sourceMappingURL=useMutation.cjs.map