wip query/mutation hooks
This commit is contained in:
132
src/lib/tanstack-query/hooks/use-server-result.ts
Normal file
132
src/lib/tanstack-query/hooks/use-server-result.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { useQuery, useMutation, useQueryClient, UseQueryOptions, UseMutationOptions, useSuspenseQuery } from '@tanstack/react-query';
|
||||
import { toast } from 'sonner';
|
||||
import { ServerResult } from '@/lib/tanstack-query/types';
|
||||
|
||||
export function useServerQuery<TData>(
|
||||
options: Omit<UseQueryOptions<TData, Error, TData>, 'queryFn'> & {
|
||||
queryFn: () => Promise<ServerResult<TData>>;
|
||||
showErrorToast?: boolean;
|
||||
}
|
||||
) {
|
||||
const { queryFn, showErrorToast = true, ...queryOptions } = options;
|
||||
|
||||
return useQuery({
|
||||
...queryOptions,
|
||||
queryFn: async () => {
|
||||
const result = await queryFn();
|
||||
|
||||
if (!result.success) {
|
||||
if (showErrorToast) {
|
||||
toast.error(result.error.userMessage);
|
||||
}
|
||||
throw new Error(result.error.userMessage);
|
||||
}
|
||||
|
||||
return result.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function useServerSuspenseQuery<TData>(
|
||||
options: Omit<UseQueryOptions<TData, Error, TData>, 'queryFn'> & {
|
||||
queryFn: () => Promise<ServerResult<TData>>;
|
||||
showErrorToast?: boolean;
|
||||
}
|
||||
) {
|
||||
const { queryFn, showErrorToast = true, ...queryOptions } = options;
|
||||
|
||||
return useSuspenseQuery({
|
||||
...queryOptions,
|
||||
queryFn: async () => {
|
||||
const result = await queryFn();
|
||||
|
||||
if (!result.success) {
|
||||
if (showErrorToast) {
|
||||
toast.error(result.error.userMessage);
|
||||
}
|
||||
throw new Error(result.error.userMessage);
|
||||
}
|
||||
|
||||
return result.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function useServerMutation<TData, TVariables = unknown>(
|
||||
options: Omit<UseMutationOptions<TData, Error, TVariables>, 'mutationFn'> & {
|
||||
mutationFn: (variables: TVariables) => Promise<ServerResult<TData>>;
|
||||
successMessage?: string;
|
||||
showErrorToast?: boolean;
|
||||
showSuccessToast?: boolean;
|
||||
}
|
||||
) {
|
||||
const {
|
||||
mutationFn,
|
||||
successMessage,
|
||||
showErrorToast = true,
|
||||
showSuccessToast = true,
|
||||
onSuccess,
|
||||
onError,
|
||||
...mutationOptions
|
||||
} = options;
|
||||
|
||||
return useMutation({
|
||||
...mutationOptions,
|
||||
mutationFn: async (variables: TVariables) => {
|
||||
const result = await mutationFn(variables);
|
||||
|
||||
if (!result.success) {
|
||||
if (showErrorToast) {
|
||||
toast.error(result.error.userMessage);
|
||||
}
|
||||
throw new Error(result.error.userMessage);
|
||||
}
|
||||
|
||||
return result.data;
|
||||
},
|
||||
onSuccess: (data, variables, context) => {
|
||||
if (showSuccessToast && successMessage) {
|
||||
toast.success(successMessage);
|
||||
}
|
||||
onSuccess?.(data, variables, context);
|
||||
},
|
||||
onError: (error, variables, context) => {
|
||||
onError?.(error, variables, context);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function useOptimisticMutation<TData, TVariables = unknown>(
|
||||
options: Parameters<typeof useServerMutation<TData, TVariables>>[0] & {
|
||||
queryKey: readonly (string | number)[];
|
||||
optimisticUpdate?: (oldData: any, variables: TVariables) => any;
|
||||
}
|
||||
) {
|
||||
const queryClient = useQueryClient();
|
||||
const { queryKey, optimisticUpdate, ...mutationOptions } = options;
|
||||
|
||||
return useServerMutation({
|
||||
...mutationOptions,
|
||||
onMutate: async (variables) => {
|
||||
await queryClient.cancelQueries({ queryKey });
|
||||
|
||||
const previousData = queryClient.getQueryData(queryKey);
|
||||
|
||||
if (optimisticUpdate && previousData) {
|
||||
queryClient.setQueryData(queryKey, (old: any) => optimisticUpdate(old, variables));
|
||||
}
|
||||
|
||||
return { previousData };
|
||||
},
|
||||
onError: (error, variables, context) => {
|
||||
if (context && typeof context === 'object' && 'previousData' in context && context.previousData) {
|
||||
queryClient.setQueryData(queryKey, context.previousData);
|
||||
}
|
||||
mutationOptions.onError?.(error, variables, context);
|
||||
},
|
||||
onSettled: (data, error, variables, context) => {
|
||||
queryClient.invalidateQueries({ queryKey });
|
||||
mutationOptions.onSettled?.(data, error, variables, context);
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user