Skip to main content
useUpdateMany is a modified version of TanStack Query’s useMutation for multiple update mutations. It uses the updateMany method from the dataProvider. If the dataProvider doesn’t have an updateMany method, it will call update for each item individually.

Usage

import { useUpdateMany } from "@refinedev/core";

interface IProduct {
  id: number;
  name: string;
  price: number;
  isActive: boolean;
}

const { mutate } = useUpdateMany<IProduct>();

mutate({
  resource: "products",
  ids: [1, 2, 3],
  values: {
    isActive: true,
  },
});

Parameters

You can pass parameters either to the hook or to the mutate/mutateAsync functions. Parameters passed to the mutation functions override those passed to the hook.
resource
string
Resource name for API data interactions.
ids
BaseKey[]
Array of record IDs to update.
values
TVariables
Values for the mutation function - the data to update.
mutationMode
'pessimistic' | 'optimistic' | 'undoable'
Determines when mutations are executed. See mutation modes.
undoableTimeout
number
Duration in ms to wait before executing the mutation when mutationMode = "undoable".
onCancel
(cancelMutation: () => void) => void
Provides a function to cancel the mutation when mutationMode = "undoable".
meta
MetaQuery
Meta data for the dataProvider. Can be used to pass additional parameters to data provider methods.
dataProviderName
string
If there is more than one dataProvider, you should specify which one to use.
invalidates
Array<keyof IQueryKeys>
default:"['list', 'many']"
Specify which queries should be invalidated after successful mutation. Options: 'list', 'many', 'detail', 'resourceAll', 'all'.
optimisticUpdateMap
OptimisticUpdateManyMapType<TData, TVariables>
You can use it to manage optimistic updates for different query types.
successNotification
OpenNotificationParams | false | ((data, values) => OpenNotificationParams | false)
Success notification configuration. Set to false to disable.
errorNotification
OpenNotificationParams | false | ((error, values) => OpenNotificationParams | false)
Error notification configuration. Set to false to disable.
mutationOptions
UseMutationOptions
TanStack Query’s useMutation options.
overtimeOptions
UseLoadingOvertimeOptionsProps
Configuration for loading overtime behavior.

Return Values

mutate
(params?: UseUpdateManyParams) => void
Function to trigger the mutation.
mutateAsync
(params?: UseUpdateManyParams) => Promise<UpdateManyResponse<TData>>
Async version that returns a promise.
mutation
UseMutationResult
TanStack Query’s useMutation return object.
overtime
object
Loading overtime information.

Examples

Basic Usage

import { useUpdateMany } from "@refinedev/core";

const { mutate } = useUpdateMany();

const handleUpdate = (ids: number[], values: Partial<IProduct>) => {
  mutate({
    resource: "products",
    ids,
    values,
  });
};

Bulk Status Update

import { useUpdateMany } from "@refinedev/core";

const BulkActions = ({ selectedIds }: { selectedIds: number[] }) => {
  const { mutate } = useUpdateMany();

  const activateProducts = () => {
    mutate({
      resource: "products",
      ids: selectedIds,
      values: { isActive: true },
    });
  };

  const deactivateProducts = () => {
    mutate({
      resource: "products",
      ids: selectedIds,
      values: { isActive: false },
    });
  };

  return (
    <div>
      <button onClick={activateProducts}>Activate Selected</button>
      <button onClick={deactivateProducts}>Deactivate Selected</button>
    </div>
  );
};

With Optimistic Updates

const { mutate } = useUpdateMany({
  mutationMode: "optimistic",
});

mutate({
  resource: "products",
  ids: [1, 2, 3],
  values: { isActive: true },
});

With Undoable Mode

const { mutate } = useUpdateMany({
  mutationMode: "undoable",
  undoableTimeout: 5000, // 5 seconds to undo
});

mutate({
  resource: "products",
  ids: [1, 2, 3],
  values: { isActive: true },
  onCancel: (cancelMutation) => {
    // Provide cancel button in your UI
    document.getElementById("undoBtn")?.addEventListener("click", cancelMutation);
  },
});

With Async/Await

const { mutateAsync } = useUpdateMany();

const handleBulkUpdate = async (ids: number[], values: Partial<IProduct>) => {
  try {
    const result = await mutateAsync({
      resource: "products",
      ids,
      values,
    });
    console.log("Updated products:", result.data);
  } catch (error) {
    console.error("Failed to update products:", error);
  }
};

With Callbacks

const { mutate } = useUpdateMany({
  mutationOptions: {
    onSuccess: (data) => {
      console.log("Updated products:", data.data);
    },
    onError: (error) => {
      console.error("Error:", error.message);
    },
  },
});

mutate({
  resource: "products",
  ids: [1, 2, 3],
  values: { isActive: true },
});

Custom Optimistic Update

const { mutate } = useUpdateMany({
  optimisticUpdateMap: {
    list: (previous, values, ids) => {
      if (!previous) return null;
      
      return {
        ...previous,
        data: previous.data.map((item) =>
          ids.includes(item.id)
            ? { ...item, ...values, updatedAt: new Date().toISOString() }
            : item
        ),
      };
    },
  },
});

Disable Notifications

const { mutate } = useUpdateMany({
  successNotification: false,
  errorNotification: false,
});

With Meta Data

const { mutate } = useUpdateMany();

mutate({
  resource: "products",
  ids: [1, 2, 3],
  values: { isActive: true },
  meta: {
    headers: { "X-Custom-Header": "value" },
  },
});

Type Parameters

  • TData - Result data type of the mutation. Extends BaseRecord.
  • TError - Custom error type that extends HttpError.
  • TVariables - Type of the values/payload for the mutation.

FAQ

If the dataProvider doesn’t implement the updateMany method, Refine will automatically fall back to calling the update method for each ID individually.
  • pessimistic (default): UI updates after server confirms
  • optimistic: UI updates immediately, rolls back on error
  • undoable: UI updates immediately with option to undo before server request
Learn more about mutation modes
Yes, set invalidates to an empty array:
mutate({
  resource: "products",
  ids: [1, 2, 3],
  values: { isActive: true },
  invalidates: [],
});

Build docs developers (and LLMs) love