import * as React from 'react'; import { QueryClient, useIsMutating } from '@tanstack/react-query'; import fakeRestDataProvider from 'ra-data-fakerest'; import { CoreAdmin, CoreAdminContext, Resource } from '../core'; import { useCreate } from './useCreate'; import { useGetOne } from './useGetOne'; import type { MutationMode as MutationModeType } from '../types'; import { CreateBase, ListBase, RecordsIterator, useRegisterMutationMiddleware, } from '../controller'; import { useNotificationContext } from '../notification'; import { useTakeUndoableMutation } from './undo'; import { Form, InputProps, useInput } from '../form'; import { TestMemoryRouter } from '../routing'; import { testDataProvider } from './testDataProvider'; import { useRefresh } from './useRefresh'; export default { title: 'ra-core/dataProvider/useCreate' }; export const MutationMode = ({ timeout = 1000 }) => { const posts = [{ id: 1, title: 'Hello', author: 'John Doe' }]; const dataProvider = { getOne: (resource, params) => { return new Promise((resolve, reject) => { const data = posts.find(p => p.id === params.id); setTimeout(() => { if (!data) { reject(new Error('nothing yet')); } resolve({ data }); }, timeout); }); }, create: (resource, params) => { return new Promise(resolve => { setTimeout(() => { posts.push(params.data); resolve({ data: params.data }); }, timeout); }); }, } as any; return ( ); }; const MutationModeCore = () => { const isMutating = useIsMutating(); const [success, setSuccess] = React.useState(); const [mutationMode, setMutationMode] = React.useState('pessimistic'); const { isPending: isPendingGetOne, data, error, refetch, } = useGetOne('posts', { id: 2 }); const [create, { isPending }] = useCreate( 'posts', { data: { id: 2, title: 'Hello World' }, }, { mutationMode, onSuccess: () => setSuccess('success'), } ); const handleClick = () => { create(); }; return ( <> {isPendingGetOne ? (

Loading...

) : error ? (

{error.message}

) : (
id
{data?.id}
title
{data?.title}
author
{data?.author}
)}
   
{success &&
{success}
} {isMutating !== 0 &&
mutating
} ); }; export const Params = ({ timeout = 1000 }) => { const posts = [{ id: 1, title: 'Hello', author: 'John Doe' }]; const dataProvider = { getOne: (resource, params) => { return new Promise((resolve, reject) => { const data = posts.find(p => p.id === params.id); setTimeout(() => { if (!data) { reject(new Error('nothing yet')); } resolve({ data }); }, timeout); }); }, create: (resource, params) => { return new Promise(resolve => { setTimeout(() => { posts.push(params.data); resolve({ data: params.data }); }, timeout); }); }, } as any; return ( ); }; const ParamsCore = () => { const isMutating = useIsMutating(); const [success, setSuccess] = React.useState(); const [params, setParams] = React.useState({ title: 'Hello World' }); const { isPending: isPendingGetOne, data, error, refetch, } = useGetOne('posts', { id: 2 }); const [create, { isPending }] = useCreate( 'posts', { data: { id: 2, ...params }, }, { mutationMode: 'optimistic', onSuccess: () => setSuccess('success'), } ); const handleClick = () => { create(); }; return ( <> {isPendingGetOne ? (

Loading...

) : error ? (

{error.message}

) : (
id
{data?.id}
title
{data?.title}
author
{data?.author}
)}
   
{success &&
{success}
} {isMutating !== 0 &&
mutating
} ); }; export const Middleware = ({ middleware = (resource: string, params: any) => { console.log( `Creating resource ${resource} with params:`, JSON.stringify(params) ); }, mutationMode = 'undoable', timeout = 1000, }: { mutationMode?: MutationModeType; timeout?: number; middleware?: (resource: string, params: any) => void; }) => { const posts = [{ id: 1, title: 'Hello', author: 'John Doe' }]; const dataProvider = testDataProvider({ // @ts-ignore getList: () => { return Promise.resolve({ data: posts, total: posts.length, }); }, create: (resource, params) => { return new Promise(resolve => { setTimeout(() => { const post = { id: posts.length + 1, ...params.data }; // @ts-ignore posts.push(post); // @ts-ignore resolve({ data: post }); }, timeout); }); }, }); return ( ( <> {children} )} >
  • {record.title}
  • } />
} create={ ({ id: mutationMode === 'pessimistic' ? undefined : posts.length + 1, ...data, })} >
} />
); }; Middleware.args = { timeout: 1000, mutationMode: 'optimistic', }; Middleware.argTypes = { timeout: { control: { type: 'number', }, }, mutationMode: { control: { type: 'select', }, options: ['pessimistic', 'optimistic', 'undoable'], }, }; const CreateMiddleware = ({ middleware, }: { middleware: (resource: string, params: any) => void; }) => { useRegisterMutationMiddleware((resource, params, next) => { middleware(resource, params); return next(resource, params); }); return null; }; const Notification = () => { const { notifications, resetNotifications } = useNotificationContext(); const takeMutation = useTakeUndoableMutation(); return notifications.length > 0 ? ( <>
{notifications[0].message}
) : null; }; const TextInput = (props: InputProps) => { const { field, id } = useInput(props); return (
); }; const RefreshButton = () => { const refresh = useRefresh(); return ( ); }; export const InvalidateList = ({ mutationMode, }: { mutationMode: MutationModeType; }) => { const dataProvider = fakeRestDataProvider( { posts: [ { id: 1, title: 'Hello' }, { id: 2, title: 'World' }, ], }, process.env.NODE_ENV !== 'test', process.env.NODE_ENV === 'test' ? 10 : 1000 ); return (
{mutationMode !== 'pessimistic' && ( )} } list={ Loading...

}> (
{record.id}: {record.title}
)} />
} />
); }; InvalidateList.args = { mutationMode: 'undoable', }; InvalidateList.argTypes = { mutationMode: { control: { type: 'select', }, options: ['pessimistic', 'optimistic', 'undoable'], }, }; export const CreateIdZero = ({ mutationMode, }: { mutationMode: MutationModeType; }) => { const dataProvider = fakeRestDataProvider( { posts: [], }, process.env.NODE_ENV !== 'test', process.env.NODE_ENV === 'test' ? 10 : 1000 ); return (
{mutationMode !== 'pessimistic' && ( )} } list={ Loading...

}> (
{record.id}: {record.title}
)} />
} />
); }; CreateIdZero.args = { mutationMode: 'undoable', }; CreateIdZero.argTypes = { mutationMode: { control: { type: 'select', }, options: ['pessimistic', 'optimistic', 'undoable'], }, };