Skip to main content
useCreate is a modified version of TanStack Query’s useMutation for create mutations. It uses the create method from the dataProvider.

Usage

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

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

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

mutate({
  resource: "products",
  values: {
    name: "New Product",
    price: 99.99,
  },
});

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.
values
TVariables
Values for the mutation function - the data to create.
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'.
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?: UseCreateParams) => void
Function to trigger the mutation.
mutateAsync
(params?: UseCreateParams) => Promise<CreateResponse<TData>>
Async version that returns a promise.
mutation
UseMutationResult
TanStack Query’s useMutation return object.
overtime
object
Loading overtime information.

Examples

Basic Usage

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

const { mutate } = useCreate();

const handleSubmit = (values: IProduct) => {
  mutate({
    resource: "products",
    values,
  });
};

With Async/Await

const { mutateAsync } = useCreate();

const handleSubmit = async (values: IProduct) => {
  try {
    const result = await mutateAsync({
      resource: "products",
      values,
    });
    console.log("Created product:", result.data);
  } catch (error) {
    console.error("Failed to create product:", error);
  }
};

Pre-configured Hook

const { mutate } = useCreate({
  resource: "products",
});

// Now you only need to pass values
mutate({
  values: {
    name: "Product",
    price: 99,
  },
});

With Callbacks

const { mutate } = useCreate({
  mutationOptions: {
    onSuccess: (data) => {
      console.log("Product created:", data.data);
    },
    onError: (error) => {
      console.error("Error:", error.message);
    },
  },
});

mutate({
  resource: "products",
  values: { name: "Product", price: 99 },
});

Custom Invalidation

const { mutate } = useCreate();

mutate({
  resource: "products",
  values: { name: "Product", price: 99 },
  invalidates: ["list", "many", "detail"],
});

Disable Notifications

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

Custom Notifications

const { mutate } = useCreate({
  successNotification: (data, values) => ({
    message: `${data.data.name} created successfully!`,
    description: "Success",
    type: "success",
  }),
  errorNotification: (error) => ({
    message: "Failed to create product",
    description: error.message,
    type: "error",
  }),
});

With Meta Data

const { mutate } = useCreate();

mutate({
  resource: "products",
  values: { name: "Product", price: 99 },
  meta: {
    headers: { "X-Custom-Header": "value" },
  },
});

With Loading State

const { mutate, mutation } = useCreate();

const handleSubmit = (values: IProduct) => {
  mutate({
    resource: "products",
    values,
  });
};

return (
  <form onSubmit={handleSubmit}>
    {/* form fields */}
    <button type="submit" disabled={mutation.isPending}>
      {mutation.isPending ? "Creating..." : "Create Product"}
    </button>
  </form>
);

Optimistic Updates

import { useQueryClient } from "@tanstack/react-query";
import { useCreate } from "@refinedev/core";

const queryClient = useQueryClient();

const { mutate } = useCreate({
  mutationOptions: {
    onMutate: async (variables) => {
      // Cancel outgoing refetches
      await queryClient.cancelQueries({ queryKey: ["products", "list"] });

      // Snapshot the previous value
      const previousProducts = queryClient.getQueryData(["products", "list"]);

      // Optimistically update
      queryClient.setQueryData(["products", "list"], (old: any) => ({
        ...old,
        data: [...old.data, { ...variables.values, id: "temp" }],
      }));

      return { previousProducts };
    },
    onError: (err, variables, context) => {
      // Rollback on error
      if (context?.previousProducts) {
        queryClient.setQueryData(["products", "list"], context.previousProducts);
      }
    },
  },
});

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

Access it from the data property:
const { mutate } = useCreate({
  mutationOptions: {
    onSuccess: (data) => {
      console.log("Created ID:", data.data.id);
    },
  },
});
Yes, set invalidates to an empty array:
mutate({
  resource: "products",
  values: { name: "Product" },
  invalidates: [],
});
Validation errors are included in the error object:
const { mutate } = useCreate({
  mutationOptions: {
    onError: (error) => {
      if (error.errors) {
        // Handle validation errors
        console.log(error.errors);
      }
    },
  },
});

Build docs developers (and LLMs) love