FormField overrides ID passed to an input
🐛 Bug Report
describe('with an id', () => {
test('should render a color input with an id', () => {
const {getByTestId} = render(
<FormField label="Color Input">
<ColorInput id="my-id" value={value} data-testid={id} />
</FormField>
);
expect(getByTestId(id)).toHaveAttribute('id', 'my-id');
});
});
Expected the element to have attribute:
id="my-id"
Received:
id="7e50e492-3eff-4354-92c8-2fce8c2267cd"
Expected Behavior
If an ID is set on an input prop, the FormField should use that ID for the label's for attribute.
Actual Results
The FormField ignores the child ID.
This could be an inversion of control issue. The FormField owns the label element which needs the same ID value as the input. The FormField taking the id value of the (a child component/element) violates the unidirectional data-flow paradigm of React. It is technically possible though, but does have plenty of edge cases.
We could message this better by perhaps warning in development mode that the ID is going to be overridden. Right now the FormField uses React.Children to map over all children and uses React.cloneElement to overwrite the id of all of them. I think using Context would be a better approach. If the "input" is a custom React component, it would need to forward on the ID parameter for everything to work properly which is an implicit API. A FormFieldContext would be a formalized API to pass down an ID.
We still need to support the use case where inputs are used without FormField though.
Closing. This is resolved with the new FormField component. #1308