usePersistedState

useState that survives reloads: the value is saved under a key in localStorage on the web (AsyncStorage on native when installed, or any storage you pass) and shared by every component using that key.
Pick a view, then reload the page: the choice is read back from localStorage. usePersistedState(key, defaultValue, options?) returns [value, setValue, { remove, ready }]. setValue takes a value or an updater like useState, and remove() deletes the stored value so the state falls back to the default.
Values are stored as JSON; pass serialize / deserialize to change that, and throw from deserialize to reject a stale or hand-edited value. ready is false during static rendering and hydration (the state shows the default so the markup matches) and while an async storage such as AsyncStorage is loading. Pass storage for anything else with getItem / setItem / removeItem, for example sessionStorage or an MMKV adapter.

Loading demo…

import { Block, Button, SegmentedControl, usePersistedState } from '@plocks/ui'; const VIEWS = [ { label: 'Grid', value: 'grid' }, { label: 'List', value: 'list' }, { label: 'Table', value: 'table' }, ]; export function Demo() { const [view, setView, { remove }] = usePersistedState('plocks-demo:view', 'grid'); return ( <Block align="center" gap="sm"> <SegmentedControl data={VIEWS} value={view} onChange={setView} /> <Button size="sm" variant="subtle" onPress={remove}> Reset </Button> </Block> ); }