useControlled
useControlled is a custom hook that helps you manage controlled components. It is a wrapper around useState that allows you to control the value of a component from the outside.
useControlled returns a [value, setValue] tuple that behaves like useState when the first argument is undefined (uncontrolled mode), or mirrors the provided value when it is defined (controlled mode). An optional onChange callback is invoked whenever the value changes. This pattern is essential for building components that need to work both as controlled and uncontrolled inputs.
When to Use
- Building reusable form components (inputs, selects, sliders) that must support both controlled and uncontrolled usage
- Wrapping third-party components that require a controlled interface while still providing a sensible uncontrolled default
- Implementing component libraries where consumers decide whether to own the state or let the component manage it
Notes
- No mode switching: The hook does not support switching between controlled and uncontrolled modes after initial mount. Choose one mode at creation time.
- No function updater: Unlike
useState, the setter does not accept a(prev) => nextfunction form. Pass values directly. - See also
useSetStatefor a class-component-style partial state updater.
Usage
Live Editor
function Demo() { const [state, setState] = useState<string>(""); const [value, setValue] = useControlled(state, ""); const [value1, setValue1] = useControlled(undefined, "unControlled value"); const handleChange = (event) => { setState(event.target.value); }; const handleChange1 = (event) => { setValue1(event.target.value); }; return ( <> <input value={value} onChange={handleChange} /> <p>Controlled Value: {value}</p> <input value={value1} onChange={handleChange1} /> </> ); };
Result
API
useControlledState
Returns
[T, (value: T) => void]: A tuple with the following elements:
- The current value.
- A function to update the value.
Arguments
| Argument | Description | Type | DefaultValue |
|---|---|---|---|
| value | controlled value | T | undefined (Required) | - |
| defaultValue | default value | T (Required) | - |
| onChange | callback when value change | ((v: T, ...args: any[]) => void) | undefined | - |