Practice exercises (Katas) for React Native and Expo, aligned with the Vercel React Native Skills Quick Reference. Each Kata has a problem (incorrect code), work (your edit target), and solution (reference implementation), with tests that check work.tsx against the rule.
- Node.js 22.x LTS
- pnpm >= 10.0.0
- Expo SDK 54.x
-
Run tests for the current
work.tsx:pnpm test exercises/NN-<exercise-name>
Or use the shortcut:
pnpm test:exercise:<rule-id>
With the initial
work.tsx(same asproblem.tsx), tests fail. -
Edit
exercises/NN-<exercise-name>/work.tsxso it satisfies the rule. -
Run tests again. When your implementation matches the rule, tests pass.
-
Compare with
solution.tsxin the same folder for a reference implementation.
To reset work.tsx back to the problem version:
pnpm run exercise:<rule-id>:reset| # | Rule ID | Description |
|---|---|---|
| 01 | ui-pressable | Use Pressable over TouchableOpacity |
| 02 | ui-safe-area-scroll | Use contentInsetAdjustmentBehavior on ScrollView |
| 03 | ui-scrollview-content-inset | Use contentInset for dynamic ScrollView spacing |
| 04 | ui-expo-image | Use expo-image for optimized images |
| 05 | ui-image-gallery | Use Galeria for image lightbox |
| 06 | ui-menus | Use native menus (zeego) for dropdowns |
| 07 | ui-native-modals | Use native Modal over JS bottom sheets |
| 08 | ui-measure-views | Use onLayout, not measure() |
| 09 | ui-styling | Use StyleSheet.create, gap, borderCurve |
| 10 | list-performance-virtualize | Use FlashList for large lists |
| 11 | list-performance-item-memo | Memoize list item components |
| 12 | list-performance-callbacks | Stabilize callback references |
| 13 | list-performance-inline-objects | Avoid inline style objects in lists |
| 14 | list-performance-function-references | Extract functions outside render |
| 15 | list-performance-images | Optimize images in lists |
| 16 | list-performance-item-expensive | Move expensive work outside items |
| 17 | list-performance-item-types | Use item types for heterogeneous lists |
| 18 | animation-gpu-properties | Animate only transform and opacity |
| 19 | animation-derived-value | Use useDerivedValue for computed animations |
| 20 | animation-gesture-detector-press | Use Gesture.Tap instead of Pressable |
| 21 | navigation-native-navigators | Use native stack and native tabs |
| 22 | react-state-minimize | Minimize state subscriptions |
| 23 | react-state-dispatcher | Use dispatcher pattern for callbacks |
| 24 | react-state-fallback | Show fallback on first render |
| 25 | react-compiler-destructure-functions | Destructure for React Compiler |
| 26 | react-compiler-reanimated-shared-values | Handle shared values with compiler |
| 27 | rendering-text-in-text-component | Wrap text in Text components |
| 28 | rendering-no-falsy-and | Avoid falsy && for conditional rendering |
| 29 | monorepo-native-deps-in-app | Keep native deps in app package |
| 30 | monorepo-single-dependency-versions | Single versions across packages |
| 31 | fonts-config-plugin | Use config plugins for custom fonts |
| 32 | imports-design-system-folder | Organize design system imports |
| 33 | js-hoist-intl | Hoist Intl object creation |
Rule details: .agents/skills/vercel-react-native-skills/rules/
Full guide: SKILL.md | AGENTS.md