mirror of
https://github.com/logto-io/logto.git
synced 2025-01-20 21:32:31 -05:00
ab7a35267a
* refactor(ui): useSocial hooks refactor useSOcial hooks refactor * fix(ui): remove unnecsessary loading on setting query remove unnecessary loading
98 lines
2.4 KiB
TypeScript
98 lines
2.4 KiB
TypeScript
import { LogtoErrorCode } from '@logto/phrases';
|
|
import { RequestErrorBody } from '@logto/schemas';
|
|
import { HTTPError } from 'ky';
|
|
import { useState, useCallback, useContext, useEffect } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import { PageContext } from '@/hooks/use-page-context';
|
|
|
|
type UseApi<T extends any[], U> = {
|
|
result?: U;
|
|
error: RequestErrorBody | undefined;
|
|
run: (...args: T) => Promise<U | undefined>;
|
|
};
|
|
|
|
export type ErrorHandlers = {
|
|
[key in LogtoErrorCode]?: (error: RequestErrorBody) => void;
|
|
} & {
|
|
global?: (error: RequestErrorBody) => void; // Overwrite default global error handle logic
|
|
callback?: (error: RequestErrorBody) => void; // Callback method
|
|
};
|
|
|
|
function useApi<Args extends any[], Response>(
|
|
api: (...args: Args) => Promise<Response>,
|
|
errorHandlers?: ErrorHandlers
|
|
): UseApi<Args, Response> {
|
|
const { t } = useTranslation(undefined, { keyPrefix: 'main_flow' });
|
|
const [error, setError] = useState<RequestErrorBody>();
|
|
const [result, setResult] = useState<Response>();
|
|
|
|
const { setLoading, setToast } = useContext(PageContext);
|
|
|
|
const parseError = useCallback(
|
|
async (error: unknown) => {
|
|
if (error instanceof HTTPError) {
|
|
try {
|
|
const kyError = await error.response.json<RequestErrorBody>();
|
|
setError(kyError);
|
|
} catch {
|
|
setToast(t('error.unknown'));
|
|
console.log(error);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
setToast(t('error.unknown'));
|
|
console.log(error);
|
|
},
|
|
[setToast, t]
|
|
);
|
|
|
|
const run = useCallback(
|
|
async (...args: Args) => {
|
|
setLoading(true);
|
|
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
setError(undefined);
|
|
|
|
try {
|
|
const result = await api(...args);
|
|
setResult(result);
|
|
|
|
return result;
|
|
} catch (error: unknown) {
|
|
void parseError(error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
},
|
|
[api, parseError, setLoading]
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (!error) {
|
|
return;
|
|
}
|
|
|
|
const { code } = error;
|
|
const handler = errorHandlers?.[code] ?? errorHandlers?.global;
|
|
|
|
errorHandlers?.callback?.(error);
|
|
|
|
if (handler) {
|
|
handler(error);
|
|
|
|
return;
|
|
}
|
|
|
|
setToast(t('error.request', { ...error }));
|
|
}, [error, errorHandlers, setToast, t]);
|
|
|
|
return {
|
|
error,
|
|
result,
|
|
run,
|
|
};
|
|
}
|
|
|
|
export default useApi;
|