Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Conform · Hook

unstable_useControl

useControl connects a custom React UI to a hidden native form control so Conform can observe values and browser-like events. It is intended for widgets such as date pickers, rich selects, and toggles.

How it works

useControl bridges a custom React component to a hidden native form control. Register the native element, use the control's current state to render the custom UI, call change when the UI value changes, and call blur when interaction leaves the logical control; focus can be delegated through the hook's callback.

Syntax

const control = useControl(options);

Parameters

NameTypeDescription
optionsUseControlOptionsAn options object for configuring the control, including the field name and optional initial value; the hook also accepts configuration used to identify the form control.

Returns

A control object that registers the native element and exposes synchronized state plus helpers such as register(), change(), blur(), and focus().

Key points

  • The hook is designed to bridge custom widgets such as selects, date pickers, and toggles with a native form control.
  • Start by rendering a hidden native element and registering it with the returned control.
  • The registered native control owns the submitted value and provides the browser-facing event source.
  • Call change when the custom component produces a new value so Conform receives the update.
  • Call blur when the logical widget is exited, especially when it is more complex than a single input.
  • Use the returned state properties to make simple custom components controlled and synchronized.
  • Use payload when the custom control represents structured rather than simple scalar data.

Common mistakes

  • The hook comes from Conform's future export, so its API may change between minor releases.
  • A custom control based on useControl does not provide the same behavior before JavaScript loads.
  • Composite or portalled controls may need custom logic to avoid treating focus movement between descendants as leaving the control.

Example: Custom rating control

import { useControl } from '@conform-to/react/future';

export function Rating({ name }: { name: string }) {
  const control = useControl({ name, initialValue: '0' });

  return (
    <div>
      <input {...control.register()} type="hidden" />
      {[1, 2, 3, 4, 5].map((rating) => (
        <button
          key={rating}
          type="button"
          aria-pressed={control.value === String(rating)}
          onClick={() => control.change(String(rating))}
        >
          {rating}
        </button>
      ))}
    </div>
  );
}

Registers a hidden native control and synchronizes a custom rating UI by changing the control value.

When to use it

Date pickers

A date picker must submit a native field value while presenting a calendar UI.

Rich selects

A library select needs Conform-compatible value and event synchronization.

Custom toggles

A toggle or other custom widget needs to participate in native form handling.

Interview questions

QWhat problem does useControl solve?

useControl connects a custom UI to a hidden native form control. The native control remains the authoritative form value, while the custom component calls change and blur to emit corresponding form events.

Follow-up: Why register a native control instead of relying only on component state? The native control participates in browser form behavior and supplies the value that Conform observes.

QHow do you integrate a custom select or date picker?

Register a hidden input or another native control with control.register(). Render the custom component from control state, then call control.change(value) when the user selects a new value.

Follow-up: How should the native control type be chosen? Choose it according to the form data the submission must produce, not according to the custom widget's visual appearance.

QHow does focus handling differ from event simulation?

control.blur() dispatches blur-related form events, but it does not move actual keyboard focus. For accessibility, use the hook's focus callback or native DOM focus methods to delegate focus to the visible custom element.

Follow-up: What additional care is needed for composite widgets? Ignore focus transitions between descendants and use the component library's close callback when appropriate.

  • useInputControl
  • useForm
  • BaseControl
  • control.register
  • control.change
  • control.blur

Source: useControl. Checked 2026-10-15.