refactor(app): add rq mutation helpers [EE-3176] (#6923)

pull/6938/head
Chaim Lev-Ari 2022-05-15 10:01:08 +03:00 committed by GitHub
parent b01180bb29
commit 0ffb84aaa6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 43 deletions

View File

@ -1,37 +1,18 @@
import { ReactQueryDevtools } from 'react-query/devtools';
import {
MutationCache,
QueryCache,
QueryClient,
QueryClientProvider,
} from 'react-query';
import { QueryClientProvider } from 'react-query';
import { UIRouterContextComponent } from '@uirouter/react-hybrid';
import { PropsWithChildren, StrictMode, useState, useEffect } from 'react';
import { PropsWithChildren, StrictMode } from 'react';
import { UserProvider } from '@/portainer/hooks/useUser';
import { UIStateProvider } from '@/portainer/hooks/UIStateProvider';
import { notifyError } from '@/portainer/services/notifications';
const queryClient = new QueryClient({
mutationCache: new MutationCache({
onError: (error, variable, context, mutation) => {
handleError(error, mutation.meta?.error);
},
}),
queryCache: new QueryCache({
onError: (error, mutation) => {
handleError(error, mutation.meta?.error);
},
}),
});
import { createQueryClient } from './react-query';
const queryClient = createQueryClient();
export function RootProvider({ children }: PropsWithChildren<unknown>) {
const [showReactQueryDevtools, setShowReactQueryDevtools] = useState(false);
useEffect(() => {
if (process.env.SHOW_REACT_QUERY_DEV_TOOLS === 'true') {
setShowReactQueryDevtools(true);
}
}, []);
const showReactQueryDevtools =
process.env.SHOW_REACT_QUERY_DEV_TOOLS === 'true';
return (
<StrictMode>
@ -46,20 +27,3 @@ export function RootProvider({ children }: PropsWithChildren<unknown>) {
</StrictMode>
);
}
function handleError(error: unknown, errorMeta?: unknown) {
if (errorMeta && typeof errorMeta === 'object') {
if (!('title' in errorMeta)) {
return;
}
const { title, message } = errorMeta as {
title: unknown;
message?: unknown;
};
if (typeof title === 'string') {
notifyError(title, error as Error, message as string);
}
}
}

View File

@ -0,0 +1,95 @@
import {
MutationCache,
MutationOptions,
QueryCache,
QueryClient,
QueryKey,
QueryOptions,
} from 'react-query';
import { notifyError } from '@/portainer/services/notifications';
export function withError(fallbackMessage?: string, title = 'Failure') {
return {
onError(error: unknown) {
notifyError(title, error as Error, fallbackMessage);
},
};
}
export function withGlobalError(fallbackMessage?: string, title = 'Failure') {
return {
meta: {
error: { message: fallbackMessage, title },
},
};
}
type OptionalReadonly<T> = T | Readonly<T>;
export function withInvalidate(
queryClient: QueryClient,
queryKeysToInvalidate: OptionalReadonly<string[]>[]
) {
return {
onSuccess() {
return queryKeysToInvalidate.map((keys) =>
queryClient.invalidateQueries(keys)
);
},
};
}
export function mutationOptions<
TData = unknown,
TError = unknown,
TVariables = void,
TContext = unknown
>(...options: MutationOptions<TData, TError, TVariables, TContext>[]) {
return mergeOptions(options);
}
export function queryOptions<
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey
>(...options: QueryOptions<TQueryFnData, TError, TData, TQueryKey>[]) {
return mergeOptions(options);
}
function mergeOptions<T>(...options: T[]) {
return options.reduce(
(acc, option) => ({
...acc,
...option,
}),
{}
);
}
export function createQueryClient() {
return new QueryClient({
mutationCache: new MutationCache({
onError: (error, variable, context, mutation) => {
handleError(error, mutation.meta?.error);
},
}),
queryCache: new QueryCache({
onError: (error, mutation) => {
handleError(error, mutation.meta?.error);
},
}),
});
}
function handleError(error: unknown, errorMeta?: unknown) {
if (errorMeta && typeof errorMeta === 'object') {
const { title = 'Failure', message } = errorMeta as {
title?: string;
message?: string;
};
notifyError(title, error as Error, message);
}
}