useControllableState
A custom hook for managing both controlled and uncontrolled state.
If value is provided, it operates in controlled mode; if not provided, it operates in uncontrolled mode.
-
In controlled mode,
valueis managed externally, and thesetValuefunction returned by this hook cannot change the internal value. -
In uncontrolled mode,
defaultValueis used as the initial value, and thesetValuefunction returned by this hook can change the internal value.
Code
Interface
typescript
interface UseControllableStateOptions<T> {
value?: T | undefined;
defaultValue: T;
}
typescript
function useControllableState<T>({
value,
defaultValue,
}: UseControllableStateOptions<T>): [T, (nextValue: SetStateAction<T>) => void];
Options
| Name | Type | Default | Description |
|---|---|---|---|
value | T | undefined | undefined | The external state value for controlled mode. When provided, the hook operates in controlled mode. |
defaultValue | T | - | The initial value for uncontrolled mode. |
Remarks
Primary Use Cases
This hook is ideal for managing the checked state of elements like checkbox and radio in a controlled/uncontrolled split.
- Provide
valuevia props for controlled mode; omit it for uncontrolled mode.
Usage
Uncontrolled Mode
- When
valueis not provided or isundefined, the hook operates in uncontrolled mode. defaultValueis used as the initial value, and the value can be changed viasetValue.
typescript
import { useControllableState } from '@modern-kit/react';
const UncontrolledExample = () => {
const [value, setValue] = useControllableState({ defaultValue: 0 });
return (
<div>
<p>Current value: {value}</p>
<button onClick={() => setValue((prev) => (prev ?? 0) + 1)}>
Increment
</button>
<button onClick={() => setValue(0)}>Reset</button>
</div>
);
};
Controlled Mode
- When
valueis provided, the hook operates in controlled mode. - The state is managed externally and cannot be changed via the
setValuereturned fromuseControllableState.
typescript
import { useState } from 'react';
import { useControllableState } from '@modern-kit/react';
const ControlledExample = () => {
const [externalValue, setExternalValue] = useState(10);
const [value, setValue] = useControllableState({ value: externalValue, defaultValue: 0 });
return (
<div>
<p>Current value: {value}</p>
<button onClick={() => setValue((prev) => (prev ?? 0) + 1)}>
Increment internally (does not work)
</button>
<button onClick={() => setExternalValue((prev) => prev + 1)}>
Increment externally (works)
</button>
</div>
);
};
Example
Uncontrolled Mode
Uncontrolled mode - Current value: 0
Controlled Mode
Controlled mode - Current value: 10