Setting the file. One moment.
Skill 04 · Vercel React Native Skills
Subchapter 4.32
rules/state-ground-truth.mdMarkdown2 KBView on GitHub
State variables—both React useState and Reanimated shared values—should
represent the actual state of something (e.g., pressed, progress, isOpen),
not derived visual values (e.g., , , ). Derive
visual values from state using computation or interpolation.
scaleopacitytranslateYIncorrect (storing the visual output):
const scale = useSharedValue(1)
const tap = Gesture.Tap()
.onBegin(() => {
scale.set(withTiming(0.95))
})
.onFinalize(() => {
scale.set(withTiming(1))
})
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.get() }],
}))Correct (storing the state, deriving the visual):
const pressed = useSharedValue(0) // 0 = not pressed, 1 = pressed
const tap = Gesture.Tap()
.onBegin(() => {
pressed.set(withTiming(1))
})
.onFinalize(() => {
pressed.set(withTiming(0))
})
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: interpolate(pressed.get(), [0, 1], [1, 0.95]) }],
}))Why this matters:
State variables should represent real “state”, not necessarily a desired end result.
pressed) describes what’s
happening; visuals are derivedpressed = 1 is clearer than scale = 0.95pressed value can drive multiple visual
propertiesSame principle for React state:
// Incorrect: storing derived values
const [isExpanded, setIsExpanded] = useState(false)
const [height, setHeight] = useState(0)
useEffect(() => {
setHeight(isExpanded ? 200 : 0)
}, [isExpanded])
// Correct: derive from state
const [isExpanded, setIsExpanded] = useState(false)
const height = isExpanded ? 200 : 0State is the minimal truth. Everything else is derived.