canvas-kit icon indicating copy to clipboard operation
canvas-kit copied to clipboard

FormField overrides ID passed to an input

Open sahlhoff opened this issue 6 years ago • 1 comments

🐛 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.

sahlhoff avatar Jan 09 '20 22:01 sahlhoff

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.

NicholasBoll avatar Jun 16 '20 21:06 NicholasBoll

Closing. This is resolved with the new FormField component. #1308

alanbsmith avatar Sep 08 '22 22:09 alanbsmith