API
useUnits
ReactVanilla
The unit preference UI hook: the effective per-category unit record for the active locale, plus the validated setters. Reactive — components re-render when any unit changes.
const { units, setUnit, resetUnit, resetAllUnits, getUnit, getUnitValues } = useUnits()
Returns
units
- Type:
Partial<Record<UnitCategory, string>> - The effective record: per-locale defaults merged with global
setUnitoverrides. Readunits.lengthfor the length unit — never store a unit in component state alongside this, it will disagree.
setUnit
- Type:
<C extends UnitCategory>(category: C, unit: SupportedUnit<C>) => void - Writes a global override, validated against the category's supported values and persisted to
state. An invalid unit is rejected, not coerced.
resetUnit / resetAllUnits
- Type:
(category) => void/() => void - Drop one override or all of them, falling back to the per-locale defaults.
getUnit / getUnitValues
- Type:
(category) => string | undefined/(category) => string[] - The effective unit for one category, and the allowed values for building a picker.
Examples
function UnitPicker({ category }: { category: 'length' }) {
const { getUnit, getUnitValues, setUnit } = useUnits()
return (
<select value={getUnit(category)} onChange={(e) => setUnit(category, e.target.value)}>
{getUnitValues(category).map((u) => (
<option key={u} value={u}>{u}</option>
))}
</select>
)
}
Values passed to formatters are always in the category base unit — the unit only changes rendering, never the stored value. Mixing the two is the common mistake; the config reference draws the line.
Next
- Rendering with units →
useFormatter - Params vs units, the base-unit contract → stift.config.ts
- Headless unit state → Formatting (vanilla)