Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build performant React Native and Expo apps with best practices for lists, animations, and navigation
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
rules/state-ground-truth.md
1---2title: State Must Represent Ground Truth3impact: HIGH4impactDescription: cleaner logic, easier debugging, single source of truth5tags: state, derived-state, reanimated, hooks6---78## State Must Represent Ground Truth910State variables—both React `useState` and Reanimated shared values—should11represent the actual state of something (e.g., `pressed`, `progress`, `isOpen`),12not derived visual values (e.g., `scale`, `opacity`, `translateY`). Derive13visual values from state using computation or interpolation.1415**Incorrect (storing the visual output):**1617```tsx18const scale = useSharedValue(1)1920const tap = Gesture.Tap()21.onBegin(() => {22scale.set(withTiming(0.95))23})24.onFinalize(() => {25scale.set(withTiming(1))26})2728const animatedStyle = useAnimatedStyle(() => ({29transform: [{ scale: scale.get() }],30}))31```3233**Correct (storing the state, deriving the visual):**3435```tsx36const pressed = useSharedValue(0) // 0 = not pressed, 1 = pressed3738const tap = Gesture.Tap()39.onBegin(() => {40pressed.set(withTiming(1))41})42.onFinalize(() => {43pressed.set(withTiming(0))44})4546const animatedStyle = useAnimatedStyle(() => ({47transform: [{ scale: interpolate(pressed.get(), [0, 1], [1, 0.95]) }],48}))49```5051**Why this matters:**5253State variables should represent real "state", not necessarily a desired end54result.55561. **Single source of truth** — The state (`pressed`) describes what's57happening; visuals are derived582. **Easier to extend** — Adding opacity, rotation, or other effects just59requires more interpolations from the same state603. **Debugging** — Inspecting `pressed = 1` is clearer than `scale = 0.95`614. **Reusable logic** — The same `pressed` value can drive multiple visual62properties6364**Same principle for React state:**6566```tsx67// Incorrect: storing derived values68const [isExpanded, setIsExpanded] = useState(false)69const [height, setHeight] = useState(0)7071useEffect(() => {72setHeight(isExpanded ? 200 : 0)73}, [isExpanded])7475// Correct: derive from state76const [isExpanded, setIsExpanded] = useState(false)77const height = isExpanded ? 200 : 078```7980State is the minimal truth. Everything else is derived.81