# Usage Examples ## useMutationOptions - Standardized Error Handling ### Basic Example ```typescript import { useMutation } from '@tanstack/react-query'; import { useMutationOptions } from '@lilith/react-query-utils'; import { apiClient } from './api'; function useCreateUser() { const options = useMutationOptions({ operation: 'create user', successMessage: 'User created successfully!', invalidateKeys: [['users']], }); return useMutation({ mutationFn: (data) => apiClient.post('/users', data), ...options, }); } // In component function CreateUserForm() { const { mutate: createUser, isPending } = useCreateUser(); const handleSubmit = (data: CreateUserDto) => { createUser(data); // ✅ Automatically shows success toast // ✅ Automatically invalidates ['users'] query // ✅ Automatically logs errors to console }; } ``` ### Real-World Example: User Management ```typescript import { useMutation } from '@tanstack/react-query'; import { useMutationOptions } from '@lilith/react-query-utils'; import { useNavigate } from 'react-router-dom'; import { userApi } from './api/users'; // Create User Hook export function useCreateUser() { const navigate = useNavigate(); const options = useMutationOptions({ operation: 'create user', successMessage: 'Welcome aboard! Account created successfully.', invalidateKeys: [['users'], ['stats', 'user-count']], onSuccess: (user) => { // Custom logic after success navigate(`/users/${user.id}`); }, }); return useMutation({ mutationFn: userApi.create, ...options, }); } // Update User Hook export function useUpdateUser() { const options = useMutationOptions({ operation: 'update user', successMessage: 'Profile updated successfully!', invalidateKeys: [ ['users'], ['users', 'id'], // Will be replaced with actual ID ], }); return useMutation({ mutationFn: ({ id, data }) => userApi.update(id, data), ...options, }); } // Delete User Hook export function useDeleteUser() { const options = useMutationOptions({ operation: 'delete user', successMessage: 'User deleted successfully.', invalidateKeys: [['users'], ['stats', 'user-count']], onSuccess: () => { // Redirect to users list after deletion window.location.href = '/users'; }, }); return useMutation({ mutationFn: userApi.delete, ...options, }); } ``` ### Example: Silent Operations ```typescript // No toast notification for background operations export function useSyncUserSettings() { const options = useMutationOptions({ operation: 'sync settings', successMessage: false, // No toast invalidateKeys: [['settings']], enableErrorLogging: false, // No console logs }); return useMutation({ mutationFn: settingsApi.sync, ...options, }); } ``` ### Example: Complex Invalidation ```typescript // Invalidate multiple related queries export function usePublishPost() { const options = useMutationOptions({ operation: 'publish post', successMessage: 'Your post is now live!', invalidateKeys: [ ['posts'], // All posts ['posts', 'published'], // Published posts filter ['user', 'me', 'posts'], // Current user's posts ['stats', 'post-count'], // Post count stats ], }); return useMutation({ mutationFn: postApi.publish, ...options, }); } ``` ### Example: Custom Error Handling ```typescript import { analytics } from './analytics'; export function useSubscribeToPlan() { const options = useMutationOptions({ operation: 'subscribe to plan', successMessage: 'Subscription activated!', invalidateKeys: [['subscription'], ['user', 'me']], onSuccess: (subscription) => { // Track successful subscription analytics.track('Subscription Created', { planId: subscription.planId, amount: subscription.amount, }); }, onError: (error) => { // Custom error tracking if (error.response?.status === 402) { analytics.track('Payment Failed', { reason: error.response.data.message, }); } }, }); return useMutation({ mutationFn: subscriptionApi.create, ...options, }); } ``` ## Before/After Comparison ### Before: Manual Error Handling (70 lines) ```typescript import { useMutation, useQueryClient } from '@tanstack/react-query'; import { getErrorMessage } from '@lilith/api-client'; import toast from 'react-hot-toast'; export function useCreateUser() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data) => apiClient.post('/users', data), onSuccess: (user) => { toast.success('User created successfully!'); queryClient.invalidateQueries({ queryKey: ['users'] }); queryClient.invalidateQueries({ queryKey: ['stats', 'user-count'] }); }, onError: (error) => { const message = getErrorMessage(error); toast.error(message || 'Failed to create user'); console.error('[create user] Error:', error); }, }); } export function useUpdateUser() { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ id, data }) => apiClient.patch(`/users/${id}`, data), onSuccess: (user, variables) => { toast.success('Profile updated successfully!'); queryClient.invalidateQueries({ queryKey: ['users'] }); queryClient.invalidateQueries({ queryKey: ['users', variables.id] }); }, onError: (error) => { const message = getErrorMessage(error); toast.error(message || 'Failed to update user'); console.error('[update user] Error:', error); }, }); } export function useDeleteUser() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (id) => apiClient.delete(`/users/${id}`), onSuccess: () => { toast.success('User deleted successfully.'); queryClient.invalidateQueries({ queryKey: ['users'] }); queryClient.invalidateQueries({ queryKey: ['stats', 'user-count'] }); }, onError: (error) => { const message = getErrorMessage(error); toast.error(message || 'Failed to delete user'); console.error('[delete user] Error:', error); }, }); } ``` ### After: Using useMutationOptions (30 lines - 57% reduction) ```typescript import { useMutation } from '@tanstack/react-query'; import { useMutationOptions } from '@lilith/react-query-utils'; export function useCreateUser() { const options = useMutationOptions({ operation: 'create user', successMessage: 'User created successfully!', invalidateKeys: [['users'], ['stats', 'user-count']], }); return useMutation({ mutationFn: (data) => apiClient.post('/users', data), ...options, }); } export function useUpdateUser() { const options = useMutationOptions({ operation: 'update user', successMessage: 'Profile updated successfully!', invalidateKeys: [['users']], }); return useMutation({ mutationFn: ({ id, data }) => apiClient.patch(`/users/${id}`, data), ...options, }); } export function useDeleteUser() { const options = useMutationOptions({ operation: 'delete user', successMessage: 'User deleted successfully.', invalidateKeys: [['users'], ['stats', 'user-count']], }); return useMutation({ mutationFn: (id) => apiClient.delete(`/users/${id}`), ...options, }); } ``` **Improvements:** - ✅ 57% less code - ✅ Standardized error handling across all mutations - ✅ Consistent toast notifications - ✅ Automatic error logging - ✅ Type-safe with TypeScript generics - ✅ Easy to customize with callbacks