useControl
This is a future API is that might subject to change in minor versions. Pin the version of
@conform-to/react
with a tilde ranges (~
) to avoid potential breaking changes.
A React hook that let you sync the state of the base input and dispatch native form events from the base input. For details on when you need this hook, see the UI Libraries Integration Guide.
const control = useControl(options);
#Options
defaultValue?: string | string[] | File | File[]
The initial value of the base input. It will be used to set the value of the input when it is first registered.
// e.g. Text input
const control = useControl({
defaultValue: 'my default value',
});
// e.g. Multi-select
const control = useControl({
defaultValue: ['option-1', 'option-3'],
});
defaultChecked?: boolean
Whether the base input should be checked by default. It will be used to set the checked state of the input when it is first registered.
const control = useControl({
defaultChecked: true,
});
value?: string
The value of the checkbox or radio input when it is checked. This is used to set the value attribute of the base input when it is first registered.
const control = useControl({
defaultChecked: true,
value: 'option-value',
});
onFocus?: () => void
A callback function that is called when the base input is focused. Use this to delegate the focus to a custom input component.
const control = useControl({
onFocus() {
controlInputRef.current?.focus();
},
});
#Returns
A control object. This gives you access to the state of the input with helpers to emulate native form events.
value: string | undefined
The current value of the base input. It will be undefined for multi-select, file inputs, or checkbox group.
options: string[] | undefined
The selected options of the base input. Use this with multi-select or checkbox groups.
checked: boolean | undefined
The checked state of the base input. Use this with checkbox or radio inputs.
files: File[] | undefined
The files selected with the base input. Use this with file inputs.
register: (element: HTMLInputElement | HTMLSelectElement | HTMLTextareaElement | Array<HTMLInputElement>) => void
Registers the base input element. This is required to sync the state of the input with the control and emits events. You can register a checkbox/ radio groups by passing an array of input elements.
change(value: string | string[] | File | File[] | FileList | boolean): void
Updates the state of the base input with both the change and input events emitted. Use this when you need to change the input value programmatically.
blur(): void
Emits 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(): void
Emits 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()
if you want to move the focus to the input element.
#Example Usage
Checkbox / Switch
1import { useControl } from '@conform-to/react/future';
2import { useForm } from '@conform-to/react';
3import { Checkbox } from './custom-checkbox-component';
4
5function Example() {
6 const [form, fields] = useForm({
7 defaultValues: {
8 newsletter: true,
9 },
10 });
11 const control = useControl({
12 defaultChecked: fields.newsletter.defaultChecked,
13 });
14
15 return (
16 <>
17 <input
18 type="checkbox"
19 name={fields.newsletter.name}
20 ref={control.register}
21 hidden
22 />
23 <Checkbox
24 checked={control.checked}
25 onChange={(checked) => control.change(checked)}
26 onBlur={() => control.blur()}
27 >
28 Subscribe to newsletter
29 </Checkbox>
30 </>
31 );
32}
Multi-select
1import { useControl } from '@conform-to/react/future';
2import { useForm } from '@conform-to/react';
3import { Select, Option } from './custom-select-component';
4
5function Example() {
6 const [form, fields] = useForm({
7 defaultValues: {
8 categories: ['tutorial', 'blog'],
9 },
10 });
11 const control = useControl({
12 defualtValue: fields.categories.defaultOptions,
13 });
14
15 return (
16 <>
17 <select
18 name={fields.categories.name}
19 ref={control.register}
20 multiple
21 hidden
22 />
23 <Select
24 value={control.options}
25 onChange={(options) => control.change(options)}
26 onBlur={() => control.blur()}
27 >
28 <Option value="blog">Blog</Option>
29 <Option value="tutorial">Tutorial</Option>
30 <Option value="guide">Guide</Option>
31 </Select>
32 </>
33 );
34}
File input
1import { useControl } from '@conform-to/react/future';
2import { useForm } from '@conform-to/react';
3import { DropZone } from './custom-file-input-component';
4function Example() {
5 const [form, fields] = useForm();
6 const control = useControl();
7
8 return (
9 <>
10 <input
11 type="file"
12 name={fields.attachements.name}
13 ref={control.register}
14 hidden
15 />
16 <DropZone
17 files={control.files}
18 onChange={(files) => control.change(files)}
19 onBlur={() => control.blur()}
20 />
21 </>
22 );
23}
#Tips
Progressive enhancement
Checkbox / Radio groups
When using checkbox or radio groups, you can register the group by passing an array of input elements to the register
method. This allows you to sync the state of the entire group with the control.