$npx -y skills add callstackincubator/agent-skills --skill react-native-best-practicesProvides React Native performance optimization guidelines for FPS, TTI, bundle size, memory leaks, re-renders, and animations. Applies to tasks involving Hermes optimization, JS thread blocking, bridge overhead, FlashList, native modules, or debugging jank and frame drops.
| 1 | # React Native Best Practices |
| 2 | |
| 3 | ## Overview |
| 4 | |
| 5 | Performance optimization guide for React Native applications, covering JavaScript/React, Native (iOS/Android), and bundling optimizations. Based on Callstack's "Ultimate Guide to React Native Optimization". |
| 6 | |
| 7 | ## When to Apply |
| 8 | |
| 9 | Reference these guidelines when: |
| 10 | - Debugging slow/janky UI or animations |
| 11 | - Investigating memory leaks (JS or native) |
| 12 | - Optimizing app startup time (TTI) |
| 13 | - Reducing bundle or app size |
| 14 | - Writing native modules (Turbo Modules) |
| 15 | - Profiling React Native performance |
| 16 | - Reviewing React Native code for performance |
| 17 | |
| 18 | ## Security Notes |
| 19 | |
| 20 | - Treat shell commands in these references as local developer operations. Review them before running, prefer version-pinned tooling, and avoid piping remote scripts directly to a shell. |
| 21 | - Treat third-party libraries and plugins as dependencies that still require normal supply-chain controls: pin versions, verify provenance, and update through your standard review process. |
| 22 | - Treat remote chunk loading as first-party artifact delivery only. Prefer app-bundled chunks or signed CI release manifests; hosted chunks must come from trusted HTTPS origins you control and be pinned to the current app release. |
| 23 | |
| 24 | ## Priority-Ordered Guidelines |
| 25 | |
| 26 | | Priority | Category | Impact | Prefix | |
| 27 | |----------|----------|--------|--------| |
| 28 | | 1 | FPS & Re-renders | CRITICAL | `js-*` | |
| 29 | | 2 | Bundle Size | CRITICAL | `bundle-*` | |
| 30 | | 3 | TTI Optimization | HIGH | `native-*`, `bundle-*` | |
| 31 | | 4 | Native Performance | HIGH | `native-*` | |
| 32 | | 5 | Memory Management | MEDIUM-HIGH | `js-*`, `native-*` | |
| 33 | | 6 | Animations | MEDIUM | `js-*` | |
| 34 | |
| 35 | Impact labels are triage hints: CRITICAL first, HIGH next, MEDIUM when evidence points there. |
| 36 | |
| 37 | ## Quick Reference |
| 38 | |
| 39 | ### Optimization Workflow |
| 40 | |
| 41 | Follow this cycle for any performance issue: **Measure → Optimize → Re-measure → Validate** |
| 42 | |
| 43 | 1. **Measure**: Capture baseline metrics before changes. For runtime issues, prefer commit timeline, re-render counts, slow components, heaviest-commit breakdown, and startup/TTI when available. Component tree depth or count are optional context, not substitutes. Do not recommend memoization, atomic state, or compiler changes without a measured render or FPS problem. |
| 44 | 2. **Optimize**: Apply the targeted fix from the relevant reference |
| 45 | 3. **Re-measure**: Run the same measurement to get updated metrics |
| 46 | 4. **Validate**: Confirm improvement (e.g., FPS 45→60, TTI 3.2s→1.8s, bundle 2.1MB→1.6MB) |
| 47 | |
| 48 | If metrics did not improve, revert and try the next suggested fix. |
| 49 | |
| 50 | ### Review Guardrails |
| 51 | |
| 52 | - Check library versions before suggesting API-specific fixes. Example: FlashList v2 deprecates `estimatedItemSize`, so do not flag it as missing there. |
| 53 | - Do not suggest `useMemo` or `useCallback` dependency changes unless behavior is demonstrably incorrect or profiling shows wasted work tied to that value. |
| 54 | - Do not report stale closures speculatively. Show the stale read path, a repro, or profiler evidence before calling it out. |
| 55 | - When profiling a flow, measure the target interaction itself. Do not treat component tree depth or component count as the main performance evidence. |
| 56 | |
| 57 | ### Critical: FPS & Re-renders |
| 58 | |
| 59 | **Profile first:** |
| 60 | ```bash |
| 61 | agent-device react-devtools status |
| 62 | agent-device react-devtools wait --connected |
| 63 | agent-device react-devtools profile start |
| 64 | agent-device react-devtools profile stop |
| 65 | agent-device react-devtools profile slow --limit 5 |
| 66 | agent-device react-devtools profile rerenders --limit 5 |
| 67 | agent-device react-devtools profile timeline --limit 20 |
| 68 | ``` |
| 69 | |
| 70 | Drive the target interaction with normal `agent-device` commands between `profile start` and `profile stop`. |
| 71 | |
| 72 | Manual fallback when `agent-device` is unavailable: open React Native DevTools from Metro (`j`) or the Dev Menu, use the Profiler tab, and record the same interaction. |
| 73 | |
| 74 | For release-build React component profiling, connect [`@callstack/inspector`](https://github.com/callstackincubator/inspector#inspector) first so React DevTools can attach to the release app, then run the `agent-device react-devtools` flow above. |
| 75 | |
| 76 | **Common fixes:** |
| 77 | - Replace ScrollView with FlatList/FlashList/Legend List for long lists |
| 78 | - After profiling shows cascading re-renders, use React Compiler for automatic memoization |
| 79 | - After profiling shows broad store/context updates, use atomic state (Jotai/Zustand) to reduce re-renders |
| 80 | - Use `useDeferredValue` for expensive computations |
| 81 | |
| 82 | ### Critical: Bundle Size |
| 83 | |
| 84 | **Analyze bundle:** |
| 85 | ```bash |
| 86 | npx react-native bundle \ |
| 87 | --entry-file index.js \ |
| 88 | --bundle-output output.js \ |
| 89 | --platform ios \ |
| 90 | --sourcemap-output output. |