How to implement a autosave/background-save feature using react-admin?
I want a feature when I am editing a rich input field, such as a rich text, a background saving will push my text to server, without touch my focus and edit position.
I tried using EditController and SimpleFrom, this will re-render form and get recorder from server, and lost focus and editing position. Any example or advice on this please?
I've built a drop-in component called EditFormAutoSave
which you can simply add to an existing EditForm
for auto-save to happen. It saves all changed "dirty" fields after a short wait interval of inactivity as well es when the edit form gets unmounted to prevent any data loss.
Important: The edit form needs to have redirect={false}
set to prevent redirect from occurring after a successful auto-save.
Usage
const YourResourceEdit = props => (
<Edit mutationMode="optimistic" {...props}>
<SimpleForm redirect={false} toolbar={<EditToolbar />}>
<EditFormAutoSave waitInterval={2000} />
<TextInput source="someFieldName" />
...
</SimpleForm>
</Edit>
)
EditFormAutoSave.js
import _ from 'lodash'
import {useEffect, useRef} from 'react'
import {useEditContext} from 'react-admin'
import {useFormState} from 'react-final-form'
const EditFormAutoSave = ({waitInterval = 1000}) => {
const {dirty, valid, values} = useFormState({subscription: {
dirty: true, valid: true, values: true,
}})
const {save, saving} = useEditContext()
const shouldSaveRef = useRef()
const saveDebouncedRef = useRef()
/*
* Determine whether 'save' should be called by any of the following effects. Use a
* 'ref' instead of a 'state' so that the an unmount effect can be set up which musn't
* have state dependencies.
*/
useEffect(() => {
shouldSaveRef.current = dirty && valid && !saving
}, [dirty, saving, valid])
/*
* Debounce the 'save()' function and store it in a 'ref' for the same reason as
* above (it needs to be called on unmount which musn't have state dependencies).
*/
useEffect(() => {
saveDebouncedRef.current = _.debounce(save, waitInterval)
}, [save, waitInterval])
/*
* Whenever the form data got dirty, schedule saving data
*/
useEffect(() => {
if (shouldSaveRef.current) {
saveDebouncedRef.current({...values}, /* redirectTo= */false)
}
}, [dirty, saving, valid, values])
/*
* On component unmount submit any unsubmitted changes so that changed ("dirty") fields
* get persisted. Said differently this effects prevents data loss of unsaved changes.
*/
useEffect(() => () => {
shouldSaveRef.current && saveDebouncedRef.current.flush()
}, [])
}
export default EditFormAutoSave
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With