@knitui/hooks
useUncontrolled
Controlled/uncontrolled state for an ARBITRARY value — port of Mantine's useUncontrolled. Generalizes the boolean-only internal/use-toggle: when value is provided the state is controlled (the setter just forwards to onChange); otherwise it is tracked internally, seeded from defaultValue then finalValue. Precisely generic — no any. The returned setter is REFERENTIALLY STABLE in both the controlled and the uncontrolled branch, and that stability is load-bearing rather than a nicety. ~48 files across components, dates and sheet call this hook and hand the setter straight to a child, a context value, or a useMemo/useEffect dep list. When the setter changed identity every render, the invalidation cascaded: in Combobox a fresh setOpen made the use-combobox store a new object, which made the ComboboxContext value a new object — and because context propagation walks *past* React.memo, every option row re-rendered on every keystroke no matter how carefully it was memoized. Callers almost always pass onChange as an inline arrow, so the latest version is read through a ref (useCallbackRef) instead of being closed over. That also means a consumer who memoized a handler with [] deps around the setter still invokes the current onChange rather than the one from its first render.
Import
import { useUncontrolled } from "@knitui/hooks";Signature
export function useUncontrolled<T>({ value, defaultValue, finalValue, onChange, }: UseUncontrolledOptions<T>): UseUncontrolledReturnValue<T>Exported types: UseUncontrolledOptions, UseUncontrolledReturnValue