# mut-mutation-state: Use useMutationState for Cross-Component Mutation Tracking ## Priority: MEDIUM ## Explanation `useMutationState` allows you to access mutation state from anywhere in your component tree, not just where `useMutation` was called. Use it to show loading indicators, display optimistic updates, or track pending mutations across components. ## Bad Example ```tsx // Prop drilling mutation state function App() { const mutation = useMutation({ mutationFn: createPost }) return (
) } // Or using context for every mutation const MutationContext = createContext(null) ``` ## Good Example ```tsx // Define mutation with a key const useCreatePost = () => useMutation({ mutationKey: ['create-post'], mutationFn: createPost, }) // In the component that triggers mutation function CreatePostButton() { const mutation = useCreatePost() return ( ) } // In any other component - track mutation state function GlobalLoadingIndicator() { const pendingMutations = useMutationState({ filters: { status: 'pending' }, select: (mutation) => mutation.state.variables, }) if (pendingMutations.length === 0) return null return (
Saving {pendingMutations.length} item(s)...
) } ``` ## Good Example: Optimistic UI in Separate Component ```tsx // Mutation defined in form function TodoForm() { const createTodo = useMutation({ mutationKey: ['create-todo'], mutationFn: (todo: NewTodo) => api.createTodo(todo), }) return
...
} // Optimistic display in list (different component) function TodoList() { const { data: todos } = useQuery({ queryKey: ['todos'], queryFn: fetchTodos }) // Get pending todo creations const pendingTodos = useMutationState({ filters: { mutationKey: ['create-todo'], status: 'pending', }, select: (mutation) => mutation.state.variables as NewTodo, }) return ( ) } ``` ## Good Example: Track Specific Mutations ```tsx function PostActions({ postId }: { postId: string }) { // Track if THIS post is being deleted const isDeletingThisPost = useMutationState({ filters: { mutationKey: ['delete-post', postId], status: 'pending', }, select: () => true, }).length > 0 // Track if THIS post is being updated const isUpdatingThisPost = useMutationState({ filters: { mutationKey: ['update-post', postId], status: 'pending', }, select: () => true, }).length > 0 return (
) } ``` ## Filters Reference ```tsx useMutationState({ filters: { mutationKey: ['key'], // Match mutation key status: 'pending', // 'idle' | 'pending' | 'success' | 'error' predicate: (mutation) => bool, // Custom filter function }, select: (mutation) => { // Transform each matching mutation // mutation.state contains: variables, data, error, status, etc. return mutation.state.variables }, }) ``` ## Context - Requires `mutationKey` on mutations you want to track - Returns array of selected values from matching mutations - Updates reactively as mutations progress - Use `status` filter to track pending/success/error states - Enables optimistic UI without prop drilling - Pairs with `mutationKey` arrays for granular tracking (e.g., `['delete-post', postId]`)