Files
stack/packages/mosaic/framework/skills/vercel-react-native-skills/rules/react-state-fallback.md
T
fargo 1a822493ba format: apply repo prettier (3.8.1) to the folded skills tree
963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
2026-08-19 14:37:17 -05:00

1.7 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Use fallback state instead of initialState MEDIUM reactive fallbacks without syncing state, hooks, derived-state, props, initialState

Use fallback state instead of initialState

Use undefined as initial state and nullish coalescing (??) to fall back to parent or server values. State represents user intent only—undefined means "user hasn't chosen yet." This enables reactive fallbacks that update when the source changes, not just on initial render.

Incorrect (syncs state, loses reactivity):

type Props = { fallbackEnabled: boolean };

function Toggle({ fallbackEnabled }: Props) {
  const [enabled, setEnabled] = useState(defaultEnabled);
  // If fallbackEnabled changes, state is stale
  // State mixes user intent with default value

  return <Switch value={enabled} onValueChange={setEnabled} />;
}

Correct (state is user intent, reactive fallback):

type Props = { fallbackEnabled: boolean };

function Toggle({ fallbackEnabled }: Props) {
  const [_enabled, setEnabled] = useState<boolean | undefined>(undefined);
  const enabled = _enabled ?? defaultEnabled;
  // undefined = user hasn't touched it, falls back to prop
  // If defaultEnabled changes, component reflects it
  // Once user interacts, their choice persists

  return <Switch value={enabled} onValueChange={setEnabled} />;
}

With server data:

function ProfileForm({ data }: { data: User }) {
  const [_theme, setTheme] = useState<string | undefined>(undefined);
  const theme = _theme ?? data.theme;
  // Shows server value until user overrides
  // Server refetch updates the fallback automatically

  return <ThemePicker value={theme} onChange={setTheme} />;
}