You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
5.8 KiB
163 lines
5.8 KiB
4 months ago
|
import { __assign } from "tslib";
|
||
|
import * as React from "rehackt";
|
||
|
import { mergeOptions } from "../../utilities/index.js";
|
||
|
import { equal } from "@wry/equality";
|
||
|
import { DocumentType, verifyDocumentType } from "../parser/index.js";
|
||
|
import { ApolloError } from "../../errors/index.js";
|
||
|
import { useApolloClient } from "./useApolloClient.js";
|
||
|
/**
|
||
|
*
|
||
|
*
|
||
|
* > 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>
|
||
|
* );
|
||
|
* }
|
||
|
* ```
|
||
|
* @since 3.0.0
|
||
|
* @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]`
|
||
|
*/
|
||
|
export function useMutation(mutation, options) {
|
||
|
var client = useApolloClient(options === null || options === void 0 ? void 0 : options.client);
|
||
|
verifyDocumentType(mutation, DocumentType.Mutation);
|
||
|
var _a = React.useState({
|
||
|
called: false,
|
||
|
loading: false,
|
||
|
client: client,
|
||
|
}), result = _a[0], setResult = _a[1];
|
||
|
var ref = React.useRef({
|
||
|
result: result,
|
||
|
mutationId: 0,
|
||
|
isMounted: true,
|
||
|
client: client,
|
||
|
mutation: mutation,
|
||
|
options: options,
|
||
|
});
|
||
|
// TODO: Trying to assign these in a useEffect or useLayoutEffect breaks
|
||
|
// higher-order components.
|
||
|
{
|
||
|
Object.assign(ref.current, { client: client, options: options, mutation: mutation });
|
||
|
}
|
||
|
var execute = React.useCallback(function (executeOptions) {
|
||
|
if (executeOptions === void 0) { executeOptions = {}; }
|
||
|
var _a = ref.current, options = _a.options, mutation = _a.mutation;
|
||
|
var baseOptions = __assign(__assign({}, options), { mutation: mutation });
|
||
|
var client = executeOptions.client || ref.current.client;
|
||
|
if (!ref.current.result.loading &&
|
||
|
!baseOptions.ignoreResults &&
|
||
|
ref.current.isMounted) {
|
||
|
setResult((ref.current.result = {
|
||
|
loading: true,
|
||
|
error: void 0,
|
||
|
data: void 0,
|
||
|
called: true,
|
||
|
client: client,
|
||
|
}));
|
||
|
}
|
||
|
var mutationId = ++ref.current.mutationId;
|
||
|
var clientOptions = mergeOptions(baseOptions, executeOptions);
|
||
|
return client
|
||
|
.mutate(clientOptions)
|
||
|
.then(function (response) {
|
||
|
var _a, _b;
|
||
|
var data = response.data, errors = response.errors;
|
||
|
var error = errors && errors.length > 0 ?
|
||
|
new ApolloError({ graphQLErrors: errors })
|
||
|
: void 0;
|
||
|
var onError = executeOptions.onError || ((_a = ref.current.options) === null || _a === void 0 ? void 0 : _a.onError);
|
||
|
if (error && onError) {
|
||
|
onError(error, clientOptions);
|
||
|
}
|
||
|
if (mutationId === ref.current.mutationId &&
|
||
|
!clientOptions.ignoreResults) {
|
||
|
var result_1 = {
|
||
|
called: true,
|
||
|
loading: false,
|
||
|
data: data,
|
||
|
error: error,
|
||
|
client: client,
|
||
|
};
|
||
|
if (ref.current.isMounted && !equal(ref.current.result, result_1)) {
|
||
|
setResult((ref.current.result = result_1));
|
||
|
}
|
||
|
}
|
||
|
var onCompleted = executeOptions.onCompleted || ((_b = ref.current.options) === null || _b === void 0 ? void 0 : _b.onCompleted);
|
||
|
if (!error) {
|
||
|
onCompleted === null || onCompleted === void 0 ? void 0 : onCompleted(response.data, clientOptions);
|
||
|
}
|
||
|
return response;
|
||
|
})
|
||
|
.catch(function (error) {
|
||
|
var _a;
|
||
|
if (mutationId === ref.current.mutationId && ref.current.isMounted) {
|
||
|
var result_2 = {
|
||
|
loading: false,
|
||
|
error: error,
|
||
|
data: void 0,
|
||
|
called: true,
|
||
|
client: client,
|
||
|
};
|
||
|
if (!equal(ref.current.result, result_2)) {
|
||
|
setResult((ref.current.result = result_2));
|
||
|
}
|
||
|
}
|
||
|
var onError = executeOptions.onError || ((_a = ref.current.options) === null || _a === void 0 ? void 0 : _a.onError);
|
||
|
if (onError) {
|
||
|
onError(error, clientOptions);
|
||
|
// TODO(brian): why are we returning this here???
|
||
|
return { data: void 0, errors: error };
|
||
|
}
|
||
|
throw error;
|
||
|
});
|
||
|
}, []);
|
||
|
var reset = React.useCallback(function () {
|
||
|
if (ref.current.isMounted) {
|
||
|
var result_3 = { called: false, loading: false, client: client };
|
||
|
Object.assign(ref.current, { mutationId: 0, result: result_3 });
|
||
|
setResult(result_3);
|
||
|
}
|
||
|
}, []);
|
||
|
React.useEffect(function () {
|
||
|
ref.current.isMounted = true;
|
||
|
return function () {
|
||
|
ref.current.isMounted = false;
|
||
|
};
|
||
|
}, []);
|
||
|
return [execute, __assign({ reset: reset }, result)];
|
||
|
}
|
||
|
//# sourceMappingURL=useMutation.js.map
|