Skip to content

Commit

Permalink
Merge pull request #8445 from marmelab/fix-form-data-consumer-warning
Browse files Browse the repository at this point in the history
Fix `<FormDataConsumer>` usage with Field children
  • Loading branch information
fzaninotto committed Nov 29, 2022
2 parents c45690f + c393e92 commit 5ff83c3
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 37 deletions.
6 changes: 3 additions & 3 deletions docs/SimpleFormIterator.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ const PostEdit = () => (
);
```

**Note**: `<SimpleFormIterator>` only accepts `Input` components as children. If you want to use some `Fields` instead, you have to use a `<FormDataConsumer>` to get the correct source, as follows:
**Note**: `<SimpleFormIterator>` only accepts `Input` components as children. If you want to use some `Fields` instead, you have to use a `<FormDataConsumer>`, as follows:

```jsx
import { ArrayInput, SimpleFormIterator, DateInput, TextField, FormDataConsumer, Labeled } from 'react-admin';
Expand All @@ -156,9 +156,9 @@ import { ArrayInput, SimpleFormIterator, DateInput, TextField, FormDataConsumer,
<SimpleFormIterator disableRemove>
<DateInput source="date" />
<FormDataConsumer>
{({ getSource }) => (
{({ scopedFormData }) => (
<Labeled label="Url">
<TextField source={getSource('url')} />
<TextField source="url" record={scopedFormData} />
</Labeled>
)}
</FormDataConsumer>
Expand Down
35 changes: 1 addition & 34 deletions packages/ra-core/src/form/FormDataConsumer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ReactNode } from 'react';
import { useWatch, useFormContext, FieldValues } from 'react-hook-form';
import get from 'lodash/get';

import warning from '../util/warning';
/**
* Get the current (edited) value of the record from the form and pass it
* to a child function
Expand Down Expand Up @@ -57,49 +56,17 @@ const FormDataConsumer = (props: ConnectedProps) => {

export const FormDataConsumerView = (props: Props) => {
const { children, form, formData, source, index, ...rest } = props;
let getSourceHasBeenCalled = false;
let ret;

// If we have an index, we are in an iterator like component (such as the SimpleFormIterator)
if (typeof index !== 'undefined' && source) {
const scopedFormData = get(formData, source);
const getSource = (scopedSource: string) => {
getSourceHasBeenCalled = true;
return `${source}.${scopedSource}`;
};
const getSource = (scopedSource: string) => `${source}.${scopedSource}`;
ret = children({ formData, scopedFormData, getSource, ...rest });
} else {
ret = children({ formData, ...rest });
}

warning(
typeof index !== 'undefined' && ret && !getSourceHasBeenCalled,
`You're using a FormDataConsumer inside an ArrayInput and you did not call the getSource function supplied by the FormDataConsumer component. This is required for your inputs to get the proper source.
<ArrayInput source="users">
<SimpleFormIterator>
<TextInput source="name" />
<FormDataConsumer>
{({
formData, // The whole form data
scopedFormData, // The data for this item of the ArrayInput
getSource, // A function to get the valid source inside an ArrayInput
...rest,
}) =>
scopedFormData.name ? (
<SelectInput
source={getSource('role')} // Will translate to "users[0].role"
choices={[{id: 1, name: 'Admin'}, {id: 2, name: 'User'},
{...rest}
/>
) : null
}
</FormDataConsumer>
</SimpleFormIterator>
</ArrayInput>`
);

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

Expand Down

0 comments on commit 5ff83c3

Please sign in to comment.