useControllableState

Merge controlled and uncontrolled state into one value and setter

Installation

Overview

useControllableState merges controlled and uncontrolled state into a single [value, setValue] tuple, the pattern Radix and Base UI use internally. Build components that accept value + onValueChange for controlled use, or defaultValue for uncontrolled use, without branching the component logic.

onValueChange fires synchronously during the event in both modes, once per accepted update. Functional updates are safe in both modes: uncontrolled updates resolve against an eagerly-advanced internal ref, so multiple setValue calls in one event tick compose instead of clobbering each other; controlled updates resolve against the last-committed value, since the parent owns the state. setValue is referentially stable across renders, so it is safe in dependency arrays and memoized contexts.

Usage

API Reference

Options

Prop

Returns

PropertyTypeDescription
valueTThe current value (controlled prop or internal).
setValue(next: T | ((prev: T) => T)) => voidUpdates the value; accepts functional updates.