Skip to content

Instantly share code, notes, and snippets.

@daniloab
Created December 8, 2021 22:29
Show Gist options
  • Save daniloab/b9d05f8fa67fd3212bb16cf07e201af4 to your computer and use it in GitHub Desktop.
Save daniloab/b9d05f8fa67fd3212bb16cf07e201af4 to your computer and use it in GitHub Desktop.
import { useSnackbar } from 'notistack';
import { MutationParameters, PayloadError } from 'relay-runtime';
import { useMutation, UseMutationConfig } from 'react-relay';
export const getError = (data: any) => {
if (data?.error) {
return data.error;
}
if (data?.errors) {
return data.errors.join('\n');
}
return null;
};
export type UseMutationCallbacksArgs<TMutation extends MutationParameters> = {
mutation: any;
name: string;
success?: string | undefined;
error?: string;
shouldShowSnackbar?: boolean;
afterCompleted?: (
response: TMutation['response'],
errors: Array<PayloadError> | null,
safeValues?: any | null,
) => void | null;
afterError?: (
error: Error,
safeValues?: any | null,
response?: TMutation['response'],
) => void;
};
export const useMutationCallbacks = <TMutation extends MutationParameters>(
args: UseMutationCallbacksArgs<TMutation>,
): [
(
executeConfig: UseMutationConfig<TMutation>,
safeValues?: any | null,
) => void,
boolean,
] => {
const {
mutation,
name,
// success,
// error,
afterCompleted,
afterError,
shouldShowSnackbar = true,
} = args;
const { enqueueSnackbar } = useSnackbar();
const [execute, isPending] = useMutation(mutation);
const onCompleted =
(error = args.error, success = args.success, safeValues: any | null) =>
(response: TMutation['response']) => {
const data = response[name];
if (!data || data.error || (data.errors && data.errors.length > 0)) {
if (shouldShowSnackbar) {
enqueueSnackbar(getError(data) || error, {
variant: 'error',
});
}
afterError &&
afterError(getError(data) || error, safeValues || {}, response);
return;
}
const successMessage = data.success || success;
if (successMessage && shouldShowSnackbar) {
enqueueSnackbar(successMessage, {
variant: 'success',
});
}
afterCompleted && afterCompleted(response, safeValues);
};
const onError =
(error = args.error, safeValues: any | null) =>
(errorMutation: Error) => {
if (error && shouldShowSnackbar) {
enqueueSnackbar(error, {
variant: 'error',
});
}
afterError && afterError(errorMutation, safeValues);
};
const executeFn = (
executeConfig: UseMutationConfig<TMutation> = { variables: {} },
safeValues?: any | null,
) => {
return execute({
onCompleted: onCompleted(
executeConfig.error,
executeConfig.success,
safeValues,
),
onError: onError(executeConfig.error, safeValues),
...executeConfig,
});
};
return [executeFn, isPending];
};
@daniloab
Copy link
Author

daniloab commented Dec 8, 2021

how to use

export const UserAdd = graphql`
  mutation UserAddMutation($input: UserAddInput!) {
    UserAdd(input: $input) {
      error
      userEdge {
        __typename
        cursor
        node {
          id
          name
        }
      }
    }
  }
`;

import { UserAdd } from "UserAddMutation";

//... on component
const [userAdd] = useMutationCallbacks<UserAddMutation>({
  name: 'UserAdd',
  mutation: UserAddM,
  success: t('User successfully added'),
  error: t('An error has occurred, please try again'),
  afterCompleted: (response) => {
    history.push(
        routeTo('user.details', {
          id: response?.UserAdd?.userEdge?.node?.id,
        }),
    );
  },
});

@daniloab
Copy link
Author

daniloab commented Dec 8, 2021

created on @entria

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment