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

An input control object. This gives you access to both the input value and helpers to simulate browser events programmatically.

value

The current value of the input, used for setting up a controlled input.

change(value: string)

Updates the input value and simulates both the change and input events. Use this when you need to change the input value programmatically.

blur()

Simulates the blur and focusout events as if the user left the input. This does not actually removes keyboard focus from the current element; it just triggers the events.

focus()

Simulates the focus and focusin events as if the user focused on the input. This does not move the actual keyboard focus to the input. Use native DOM methods like inputElement.focus() for real focus control.

#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};