useCreate

This hook allows to call dataProvider.create() when the callback is executed.

Syntax

const [create, { data, isPending, error }] = useCreate(
    resource,
    { data, meta },
    options
);

The create() method can be called with the same parameters as the hook:

create(
    resource,
    { data },
    options
);

So, should you pass the parameters when calling the hook, or when executing the callback? It’s up to you; but if you have the choice, we recommend passing the parameters when calling the create callback (second example below).

Usage

// set params when calling the hook
import { useCreate, useRecordContext } from 'react-admin';

const LikeButton = () => {
    const record = useRecordContext();
    const like = { postId: record.id };
    const [create, { isPending, error }] = useCreate('likes', { data: like });
    const handleClick = () => {
        create()
    }
    if (error) { return <p>ERROR</p>; }
    return <button disabled={isPending} onClick={handleClick}>Like</button>;
};

// set params when calling the create callback
import { useCreate, useRecordContext } from 'react-admin';

const LikeButton = () => {
    const record = useRecordContext();
    const like = { postId: record.id };
    const [create, { isPending, error }] = useCreate();
    const handleClick = () => {
        create('likes', { data: like })
    }
    if (error) { return <p>ERROR</p>; }
    return <button disabled={isPending} onClick={handleClick}>Like</button>;
};

Params

The second argument of the useCreate hook is an object with the following properties:

  • data: the new data for the record,
  • meta: an object to pass additional information to the dataProvider (optional).
const LikeButton = () => {
    const record = useRecordContext();
    const like = { postId: record.id };
    const [create, { isPending, error }] = useCreate('likes', { data: like });
    const handleClick = () => {
        create()
    }
    if (error) { return <p>ERROR</p>; }
    return <button disabled={isPending} onClick={handleClick}>Like</button>;
};

data the record to create.

meta is helpful for passing additional information to the dataProvider. For instance, you can pass the current user to let a server-side audit system know who made the creation.

Options

useCreate’s third parameter is an options object with the following properties:

  • mutationMode,
  • onError,
  • onSettled,
  • onSuccess,
  • returnPromise.
const notify = useNotify();
const redirect = useRedirect();

const [create, { isPending, error }] = useCreate(
    'likes',
    { data: { id: uuid.v4(), postId: record.id } },
    {
        mutationMode: 'optimistic',
        onSuccess: () => {
            notify('Like created');
            redirect('/reviews');
        },
        onError: (error) => {
            notify(`Like creation error: ${error.message}`, { type: 'error' });
        },
    });

Additional options are passed to React Query’s useMutation hook. This includes:

  • gcTime,
  • networkMode,
  • onMutate,
  • retry,
  • retryDelay,
  • mutationKey,
  • throwOnError.

Check the useMutation documentation for a detailed description of all options.

Tip: In react-admin components that use useCreate, you can override the mutation options using the mutationOptions prop. This is very common when using mutation hooks like useCreate, e.g., to display a notification or redirect to another page.

For instance, here is a button using <Create mutationOptions> to notify the user of success using the bottom notification banner:

import * as React from 'react';
import { useNotify, useRedirect, Create, SimpleForm } from 'react-admin';

const PostCreate = () => {
    const notify = useNotify();
    const redirect = useRedirect();

    const onSuccess = (data) => {
        notify(`Changes saved`);
        redirect(`/posts/${data.id}`);
    };

    return (
        <Create mutationOptions={{ onSuccess }}>
            <SimpleForm>
                ...
            </SimpleForm>
        </Create>
    );
}

Return Value

The useCreate hook returns an array with two values:

  • the create callback, and
  • a mutation state object with the following properties:
    • data,
    • error,
    • isError,
    • isIdle,
    • isPending,
    • isPaused,
    • isSuccess,
    • failureCount,
    • failureReason,
    • mutate,
    • mutateAsync,
    • reset,
    • status,
    • submittedAt,
    • variables.

The create callback can be called with a resource and a param argument, or, if these arguments were defined when calling useCreate, with no argument at all:

// Option 1: define the resource and params when calling the callback
const [create, { isPending }] = useCreate();
const handleClick = () => {
    create(resource, params, options);
};

// Option 2: define the resource and params when calling the hook
const [create, { isPending }] = useCreate(resource, params, options);
const handleClick = () => {
    create();
};

For a detailed description of the mutation state, check React-query’s useMutation documentation.

Since useCreate is mainly used in event handlers, success and error side effects are usually handled in the onSuccess and onError callbacks. In most cases, the mutation state is just used to disable the save button while the mutation is pending.

mutationMode

The mutationMode option lets you switch between three rendering modes, which change how the success side effects are triggered:

  • pessimistic (the default)
  • optimistic, and
  • undoable

Note: For optimistic and undoable modes, the record id must be generated client side. Those two modes are useful when building local first applications.

Here is an example of using the optimistic mode:

// In optimistic mode, ids must be generated client side
const id = uuid.v4();
const [create, { data, isPending, error }] = useCreate(
    'comments',
    { data: { id, message: 'Lorem ipsum' } },
    { 
        mutationMode: 'optimistic',
        onSuccess: () => { /* ... */},
        onError: () => { /* ... */},
    }
);

In pessimistic mode, the onSuccess side effect executes after the dataProvider responds.

In optimistic mode, the onSuccess side effect executes just before the dataProvider.create() is called, without waiting for the response.

In undoable mode, the onSuccess side effect fires immediately. The actual call to the dataProvider is delayed until the create notification hides. If the user clicks the undo button, the dataProvider.create() call is never made.

See Optimistic Rendering and Undo for more details.

Tip: If you need a side effect to be triggered after the dataProvider response in optimistic and undoable modes, use the onSettled callback.

onError

The onError callback is called when the mutation fails. It’s the perfect place to display an error message to the user.

const notify = useNotify();
const [create, { data, isPending, error }] = useCreate(
    'comments',
    { id: record.id, data: { isApproved: true } },
    { 
        onError: () => {
            notify('Error: comment not approved',  { type: 'error' });
        },
    }
);

Note: If you use the retry option, the onError callback is called only after the last retry has failed.

onSettled

The onSettled callback is called at the end of the mutation, whether it succeeds or fails. It will receive either the data or the error.

const notify = useNotify();
const [create, { data, isPending, error }] = useCreate(
    'comments',
    { id: record.id, data: { isApproved: true } },
    { 
        onSettled: (data, error) => {
            // ...
        },
    }
);

Tip: The onSettled callback is perfect for calling a success side effect after the dataProvider response in optimistic and undoable modes.

onSuccess

The onSuccess callback is called when the mutation succeeds. It’s the perfect place to display a notification or to redirect the user to another page.

const notify = useNotify();
const redirect = useRedirect();
const [create, { data, isPending, error }] = useCreate(
    'comments',
    { id: record.id, data: { isApproved: true } },
    { 
        onSuccess: () => {
            notify('Comment approved');
            redirect('/comments');
        },
    }
);

In pessimistic mutation mode, onSuccess executes after the dataProvider.create() responds. React-admin passes the result of the dataProvider.create() call as the first argument to the onSuccess callback.

In optimistic mutation mode, onSuccess executes before the dataProvider.create() is called, without waiting for the response. The callback receives no argument.

In undoable mutation mode, onSuccess executes before the dataProvider.create() is called. The actual call to the dataProvider is delayed until the create notification hides. If the user clicks the undo button, the dataProvider.create() call is never made. The callback receives no argument.

returnPromise

By default, the create callback that useCreate returns is synchronous and returns nothing. To execute a side effect after the mutation has succeeded, you can use the onSuccess callback.

If this is not enough, you can use the returnPromise option so that the create callback returns a promise that resolves when the mutation has succeeded and rejects when the mutation has failed.

This can be useful if the server changes the record, and you need the newly created data to create/update another record.

const [createPost] = useCreate(
    'posts',
    { id: record.id, data: { isPublished: true } },
    { returnPromise: true }
);
const [createAuditLog] = useCreate('auditLogs');

const createPost = async () => {
    try {
        const post = await createPost();
        createAuditLog('auditLogs', { data: { action: 'create', recordId: post.id, date: post.createdAt } });
    } catch (error) {
        // handle error
    }
};

TypeScript

The useCreate hook accepts a generic parameter for the record type and another for the error type:

type Product = {
    id: number;
    reference: string;
}

useCreate<Product, Error>(undefined, undefined, {
    onError: (error) => {
        // TypeScript knows that error is of type Error
    },
    onSettled: (data, error) => {
        // TypeScript knows that data is of type Product
        // TypeScript knows that error is of type Error
    },
})