<AutoSave>
This Enterprise Edition component enables autosaving of the form. Alternative to <SaveButton>
, it’s ideal for long data entry tasks, and reduces the risk of data loss.
Test it live on the Enterprise Edition Storybook.
Usage
Put <AutoSave>
inside a react-admin form (<SimpleForm>
, <TabbedForm>
, <LongForm>
, etc.), for instance in a custom toolbar. The component renders nothing by default. It will save the current form values 3 seconds after the last change, and render a message when the save succeeds or fails.
Note that you must set the <Form resetOptions>
prop to { keepDirtyValues: true }
. If you forget that prop, any change entered by the end user after the autosave but before its acknowledgement by the server will be lost.
If you’re using it in an <Edit>
page, you must also use a pessimistic
or optimistic
mutationMode
- <AutoSave>
doesn’t work with the default mutationMode="undoable"
.
Note that <AutoSave>
does not currently work with warnWhenUnsavedChanges
.
import { AutoSave } from '@react-admin/ra-form-layout';
import { Edit, SimpleForm, TextInput, DateInput, SelectInput, Toolbar } from 'react-admin';
const AutoSaveToolbar = () => (
<Toolbar>
<AutoSave />
</Toolbar>
);
const PersonEdit = () => (
<Edit mutationMode="optimistic">
<SimpleForm
resetOptions={{ keepDirtyValues: true }}
toolbar={<AutoSaveToolbar />}
>
<TextInput source="first_name" />
<TextInput source="last_name" />
<DateInput source="dob" />
<SelectInput source="sex" choices={[
{ id: 'male', name: 'Male' },
{ id: 'female', name: 'Female' },
]}/>
</SimpleForm>
</Edit>
);
The app will save the current form values after 3 seconds of inactivity.
You can use a toolbar containing both a <SaveButton>
and an <AutoSave>
component. The <SaveButton>
will let the user save the form immediately, while the <AutoSave>
will save the form after 3 seconds of inactivity.
const AutoSaveToolbar = () => (
<Toolbar>
<SaveButton />
<AutoSave />
</Toolbar>
);
Props
Prop | Required | Type | Default | Description |
---|---|---|---|---|
debounce |
Optional | number |
3000 | The interval in ms between two saves |
onSuccess |
Optional | function |
- | A callback to call when the save succeeds |
onError |
Optional | function |
- | A callback to call when the save fails |
transform |
Optional | function |
- | A function to transform the data before saving |
useAutoSave
If you want an autosave feature with another user interface, you can leverage the useAutoSave
hook. It’s used internally by <AutoSave>
, and has the same constraints (it works for the pessimistic
and optimistic
mutationMode
but not for the undoable
).
useAutoSave
expects an options argument with the following fields, all optional:
debounce
: The interval in ms between two saves. Defaults to 3000 (3s).onSuccess
: A callback to call when the save request succeeds.onError
: A callback to call when the save request fails.transform
: A function to transform the data before saving.
Note that you must add the resetOptions
prop with { keepDirtyValues: true }
to avoid having the user changes overridden by the latest update operation result.
import { useAutoSave } from '@react-admin/ra-form-layout';
import { Edit, SaveButton, SimpleForm, TextInput, Toolbar } from 'react-admin';
const AutoSave = () => {
const [lastSave, setLastSave] = useState();
const [error, setError] = useState();
useAutoSave({
interval: 5000,
onSuccess: () => setLastSave(new Date()),
onError: error => setError(error),
});
return (
<div>
{lastSave && <p>Saved at {lastSave.toLocaleString()}</p>}
{error && <p>Error: {error}</p>}
</div>
);
};
const AutoSaveToolbar = () => (
<Toolbar>
<SaveButton />
<AutoSave />
</Toolbar>
);
const PostEdit = () => (
<Edit mutationMode="optimistic">
<SimpleForm
resetOptions={{ keepDirtyValues: true }}
toolbar={<AutoSaveToolbar />}
>
<TextInput source="title" />
<TextInput source="teaser" />
</SimpleForm>
</Edit>
);
usaAutoSave
returns a boolean indicating whether the form is currently being saved.
const isSaving = useAutoSave({
interval: 5000,
onSuccess: () => setLastSave(new Date()),
onError: error => setError(error),
});