Skip to content

Commit

Permalink
Merge pull request #10417 from marmelab/fix-form-data-consumer-flicker
Browse files Browse the repository at this point in the history
Fix form data consumer flicker
  • Loading branch information
slax57 authored Dec 17, 2024
2 parents 526d088 + b05a1a0 commit d135bd3
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 12 deletions.
29 changes: 17 additions & 12 deletions packages/ra-core/src/form/FormDataConsumer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useFormContext, FieldValues } from 'react-hook-form';
import get from 'lodash/get';
import { useFormValues } from './useFormValues';
import { useWrappedSource } from '../core';
import { useEvent } from '../util';

/**
* Get the current (edited) value of the record from the form and pass it
Expand Down Expand Up @@ -67,22 +68,26 @@ export const FormDataConsumerView = <
props: Props<TFieldValues>
) => {
const { children, formData, source } = props;
let ret;
const [result, setResult] = React.useState<ReactNode>(null);

const finalSource = useWrappedSource(source || '');
const render = useEvent(children);

// Passes an empty string here as we don't have the children sources and we just want to know if we are in an iterator
const matches = ArraySourceRegex.exec(finalSource);
// Getting the result of the children function in a useEffect allows us to keep a stable reference to is
// with useEvent
React.useEffect(() => {
// Passes an empty string here as we don't have the children sources and we just want to know if we are in an iterator
const matches = ArraySourceRegex.exec(finalSource);
// If we have an index, we are in an iterator like component (such as the SimpleFormIterator)
if (matches) {
const scopedFormData = get(formData, matches[0]);
setResult(render({ formData, scopedFormData }));
} else {
setResult(render({ formData }));
}
}, [finalSource, formData, render]);

// If we have an index, we are in an iterator like component (such as the SimpleFormIterator)
if (matches) {
const scopedFormData = get(formData, matches[0]);
ret = children({ formData, scopedFormData });
} else {
ret = children({ formData });
}

return ret === undefined ? null : ret;
return result;
};

const ArraySourceRegex = new RegExp(/.+\.\d+$/);
Expand Down
95 changes: 95 additions & 0 deletions packages/ra-ui-materialui/src/form/FormDataConsumer.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import * as React from 'react';
import { FormDataConsumer, required, ResourceContextProvider } from 'ra-core';
import fakeRestDataProvider from 'ra-data-fakerest';
import { AdminContext } from '../AdminContext';
import { AutocompleteInput, ReferenceInput, TextInput } from '../input';
import { SimpleForm } from './SimpleForm';
import { Create } from '../detail';

// We keep this test in ra-ui-materialui because we need heavy components to reproduce the issue https://github.com/marmelab/react-admin/issues/10415
export default { title: 'ra-core/form/FormDataConsumer' };

export const Basic = () => (
<AdminContext dataProvider={dataProvider}>
<ResourceContextProvider value="posts">
<Create>
<SimpleForm>
<TextInput source="title" />
<FormDataConsumer<any>>
{({ formData }) => {
console.log({ formData });
if (!formData.title) {
return null;
}
return (
<ReferenceInput
source="userId"
reference="users"
>
<AutocompleteInput
shouldUnregister
label="User"
optionText={choice =>
`${choice.name} / (${choice.id})`
}
noOptionsText="User doesn't exist"
isRequired
validate={[
required('User is required.'),
]}
/>
</ReferenceInput>
);
}}
</FormDataConsumer>
<TextInput source="body" multiline rows={5} />
</SimpleForm>
</Create>
</ResourceContextProvider>
</AdminContext>
);

const dataProvider = fakeRestDataProvider({
users: [
{
id: 1,
name: 'Leanne Graham',
},
{
id: 2,
name: 'Ervin Howell',
},
{
id: 3,
name: 'Clementine Bauch',
},
{
id: 4,
name: 'Patricia Lebsack',
},
{
id: 5,
name: 'Chelsey Dietrich',
},
{
id: 6,
name: 'Mrs. Dennis Schulist',
},
{
id: 7,
name: 'Kurtis Weissnat',
},
{
id: 8,
name: 'Nicholas Runolfsdottir V',
},
{
id: 9,
name: 'Glenna Reichert',
},
{
id: 10,
name: 'Clementina DuBuque',
},
],
});

0 comments on commit d135bd3

Please sign in to comment.