API Reference / useInputControl

useInputControl

A React hook that let you control the browser events to be dispatched. It is useful if you want to hook up a custom input to Conform.

1const control = useInputControl(metaOrOptions);

#Example

1import { useForm, useInputControl } from '@conform-to/react';
2import { Select, Option } from './custom-ui';
3
4function Example() {
5  const [form, fields] = useForm();
6  const color = useInputControl(fields.color);
7
8  return (
9    <Select
10      name={fields.color.name}
11      value={color.value}
12      onChange={color.change}
13      onFocus={color.focus}
14      onBlur={color.blur}
15    >
16      <Option value="red">Red</Option>
17      <Option value="green">Green</Option>
18      <Option value="blue">Blue</Option>
19    </Select>
20  );
21}

#Parameters

metaOrOptions

The field metadata or an options object that includes key, name, formId and initialValue.

#Returns

The input control. This gives you access to both the input value and three different event dispatchers.

value

The value on the input. This can be used to set up a controlled input.

change(value: string)

A method to be called when the value should be changed. This will dispatch both the change and input event on behalf of the input with the new value.

blur()

A method to be called when the user leaves the input. This will dispatch both the blur and focusout event on behalf of the input.

focus()

A method to be called when . This will dispatch both the focus and focusin event on behalf of the input.

#Tips

Focus delegation

Conform will focus on the first invalid input element if submission failed. However, this might not work if your have a custom input. To fix this, you can forward the focus from the input element by listening to the focus event and trigger element.focus() on the desired element.

1import { useForm, useInputControl } from '@conform-to/react';
2import { Select, Option } from './custom-ui';
3
4function Example() {
5  const [form, fields] = useForm();
6  const inputRef = useRef(null);
7  const color = useInputControl(fields.color);
8
9  return (
10    <>
11        <input
12            name={fields.color.name}
13            defaultValue={fields.color.initialValue}
14            className="sr-only"
15            tabIndex={-1}
16            onFocus={() => inputRef.current?.focus()}
17        />
18        <Select
19            ref={inputRef}
20            value={color.value}
21            onChange={color.change}
22            onFocus={color.focus}
23            onBlur={color.blur}
24        >
25            <Option value="red">Red</Option>
26            <Option value="green">Green</Option>
27            <Option value="blue">Blue</Option>
28        </Select>
29    <>
30  );
31}

In the example above, we set up a hidden input manually instead of passing a name prop to the custom select component due to no control over the inner input rendered by the custom input. The input is visually hidden but still focusable thanks to the sr-only class from tailwindcss. When the input is focused, we delegate the focus to the custom input by calling inputRef.current?.focus().

If you are not using tailwindcss, please look for a similar utility from your preferred styling solution or you can apply the following style based on the implementation of the sr-only class:

1const style = {
2  position: 'absolute',
3  width: '1px',
4  height: '1px',
5  padding: 0,
6  margin: '-1px',
7  overflow: 'hidden',
8  clip: 'rect(0,0,0,0)',
9  whiteSpace: 'nowrap',
10  border: 0,
11};