Skip to main content

enabled

Description: Defines if the useMutation hook is active or not. If this is set to false, the mutate function will not execute the action when called.

  • How To: Use enabled to programmatically control when a mutation should be allowed to run, e.g., based on form validation, user permissions, or the presence of required data.
    // Correct: Only allow updating the profile if the form is valid and dirty
    const { mutate } = useMutation({
    enabled: form.isValid && form.isDirty,
    after: () => toast.success('Profile updated!')
    });

    const onSave = () => {
    // If enabled is false, this call will do nothing
    mutate(() => api.updateProfile(form.values));
    };
  • Best Practice: While you can also disable the button in the UI, setting enabled: false in the hook provides an extra layer of protection and ensures that side effects (like before or after hooks) are also not triggered if the mutation shouldn't run.
    // Avoid this: Relying only on UI state to prevent mutation
    const { mutate } = useMutation({
    after: () => console.log('This will run even if button was disabled but clicked via console!')
    });

    return <button onClick={() => mutate(action)} disabled={!isValid}>Save</button>;

    // Instead: Guard the mutation logic itself
    const { mutate } = useMutation({
    enabled: isValid,
    after: () => console.log('Protected!')
    });

Deep Dive: How enabled works step by step

Example:

function DeleteButton({ id, canDelete }) {
const { mutate } = useMutation({
enabled: canDelete,
mutationKey: ['delete', id]
});

return <button onClick={() => mutate(() => api.delete(id))}>Delete</button>;
}

What happens step by step when canDelete is false:

  1. User clicks the buttonmutate() is called.
  2. useMutation checks the enabled option → Finds it is false.
  3. The action function is ignoredapi.delete(id) is never executed.
  4. No state changes occurisLoading remains false, isDone remains false.
  5. No lifecycle hooks runbefore and after are skipped.
  6. No network request is made → The DataClient does not initiate any fetch.

What happens step by step when canDelete is true:

  1. User clicks the buttonmutate() is called.
  2. useMutation checks the enabled option → Finds it is true.
  3. before hook executes → If defined in options.
  4. The action function is executedapi.delete(id) starts the network request.
  5. isLoading becomes true → Component re-renders (if not using suspense).
  6. Mutation completesisLoading becomes false, isSuccess or isError is set.
  7. after hook executes → Receives the response or error.

Key insight: enabled acts as a circuit breaker for the mutate function. It is particularly useful for preventing accidental mutations in complex UIs where multiple conditions must be met.