useControllableState is a hook that manages both controlled and uncontrolled state patterns, allowing components to work flexibly in either mode. It handles the complexity of switching between controlled and uncontrolled modes and provides warnings in development when incorrect patterns are detected.
Installation
Function Signature
Parameters
The controlled value from props. When provided, the component operates in controlled mode.
The default value for uncontrolled mode. This is required and serves as the initial state when
prop is undefined.Callback function invoked when the state changes. Called in both controlled and uncontrolled modes.Default:
() => {}Component name for debugging purposes. Used in development warnings when the component switches between controlled and uncontrolled modes.
Return Value
The current state value. Either the controlled
prop value or the internal uncontrolled state.Function to update the state. Handles both controlled and uncontrolled patterns automatically.
Usage
Basic Example
Controlled Mode
Uncontrolled Mode
Type Definitions
Notes
In development mode, the hook will warn you if a component switches between controlled and uncontrolled modes. This helps catch common bugs where state management patterns change unexpectedly.
The
onChange callback is stored in a ref and updated using useInsertionEffect (or useLayoutEffect as a fallback) to ensure it doesn’t cause unnecessary re-renders when passed as a dependency.