|
- import { useCallback, useMemo, useState } from "react";
- import { APICommonResponse, apiRequest, ResultCode } from "api";
- import { UseFormReturn } from "react-hook-form";
- import { Dictionary } from "@types";
- import { useSnackbar } from "notistack";
-
- export const APIErrorType = {
- NONE: "none",
- INPUT: "input",
- SERVER: "server",
- EXCLUSIVE: "exclusive",
- } as const;
- export type APIErrorType = (typeof APIErrorType)[keyof typeof APIErrorType];
-
- export default function useAPICall<
- T extends object,
- U extends APICommonResponse
- >({
- apiMethod,
- onSuccess,
- onFailed,
- form,
- successMessage = false,
- failedMessage = false,
- }: {
- apiMethod: (sendData: T) => Promise<U | null>;
- onSuccess?: (res: U, sendData: T) => void;
- onFailed?: (res: APICommonResponse | null) => void;
- form?: UseFormReturn<any>;
- successMessage?: ((res: U) => string) | boolean;
- failedMessage?: ((res: APICommonResponse | null) => string) | boolean;
- }) {
- const [sending, setSending] = useState(false);
- const [sendData, setSendData] = useState<T | null>(null);
- const [result, setResult] = useState<ResultCode | null>(null);
- const [errors, setErrors] = useState<Dictionary>({});
- const [validationError, setValidationError] = useState(false);
- const [exclusiveError, setExclusiveError] = useState(false);
- const [generalErrorMessage, setGeneralErrorMessage] = useState("");
-
- const { enqueueSnackbar } = useSnackbar();
-
- const clearErrors = () => {
- setResult(null);
- setErrors({});
- setSendData(null);
- setValidationError(false);
- setExclusiveError(false);
- setGeneralErrorMessage("");
- };
-
- // 入力項目に対してエラーレスポンスがあるか、ないかでエラーのタイプを設定する
- const errorMode = useMemo<APIErrorType>(() => {
- if (generalErrorMessage !== "") return APIErrorType.INPUT;
- if (exclusiveError) return APIErrorType.EXCLUSIVE;
- if (validationError) return APIErrorType.INPUT;
- if (result === null) return APIErrorType.NONE;
- if (result === ResultCode.SUCCESS) return APIErrorType.NONE;
- if (sendData === null) return APIErrorType.NONE;
-
- const messageKeys = Object.keys(errors);
- if (messageKeys.length === 0) return APIErrorType.SERVER;
-
- if (sendData) {
- const sendDataKeys = Object.keys(sendData);
- const find = messageKeys.find((key: string) => {
- return sendDataKeys.includes(key);
- });
- if (find) {
- return APIErrorType.INPUT;
- }
- }
- return APIErrorType.SERVER;
- }, [result, errors, validationError, exclusiveError, generalErrorMessage]);
-
- const getSuccessMessageStr = useCallback(
- (res: U) => {
- if (typeof successMessage === "boolean") {
- return successMessage ? "成功しました" : "";
- }
- return successMessage(res);
- },
- [successMessage]
- );
-
- const getFailedMessageStr = useCallback(
- (res: APICommonResponse | null) => {
- if (typeof failedMessage === "boolean") {
- return failedMessage ? "失敗しました" : "";
- }
- return failedMessage(res);
- },
- [failedMessage]
- );
-
- const successCallback = (res: U, sendData: T) => {
- setResult(ResultCode.SUCCESS);
- const message = getSuccessMessageStr(res);
- if (message) {
- enqueueSnackbar(message);
- }
- if (onSuccess) {
- onSuccess(res, sendData);
- }
- };
-
- const failedCallback = (res: APICommonResponse | null) => {
- if (res?.result === ResultCode.EXCLUSIVE_ERROR) {
- setExclusiveError(true);
- }
- if (res) {
- setResult(res.result);
- }
-
- if (res?.messages.errors) {
- console.log("seterrors", res.messages.errors);
- setErrors(res.messages.errors);
- }
- if (res?.messages.general) {
- setGeneralErrorMessage(res.messages.general);
- }
-
- const message = getFailedMessageStr(res);
- if (message) {
- enqueueSnackbar(message, { variant: "error" });
- }
- if (onFailed) {
- onFailed(res);
- }
- };
-
- const handleValidationError = (error: any) => {
- console.log(error);
- setValidationError(true);
- };
-
- const callAPI = async (sendData: T) => {
- if (form) {
- form.clearErrors();
- }
- clearErrors();
-
- setSendData(sendData);
- const res = await apiRequest({
- apiMethod,
- onSuccess: successCallback,
- onFailed: failedCallback,
- sendData,
- setSending,
- errorSetter: form?.setError,
- });
-
- return res;
- };
-
- const makeSendData = (data: T) => {
- return data;
- };
-
- return {
- callAPI,
- sending,
- errorMode,
- generalErrorMessage,
- handleValidationError,
- makeSendData,
- };
- }
|