Deft
Ask AI

Search

Search skills, authors and topics

callstackincubator / agent-skills

react-native-best-practices

React Native performance optimization guidelines for FPS, TTI, bundle size, memory leaks, re-renders, and animations.

Install

npx skills add https://github.com/callstackincubator/agent-skills --skill react-native-best-practices
license
MIT
author
Callstack
keywords
["react-native", "expo", "performance", "optimization", "profiling"]

Onboarding

Step 1: Validate React Native Setup

Before applying performance optimizations, ensure:

  • Expo CLI or React Native CLI is installed
    • Verify with: npx expo --version and npx react-native --version
  • Metro bundler is running (apply only for bundle analysis)
  • React Native DevTools profiling is available through agent-device react-devtools (apply only for React render profiling/debugging)
    • Run agent-device react-devtools status, then agent-device react-devtools wait --connected

Security Guardrails

  • Review shell commands before running them and prefer version-pinned tooling from trusted sources.
  • Do not pipe remote install scripts directly into a shell.
  • Treat third-party packages as normal supply-chain dependencies that require provenance and version review.
  • If using remote chunk loading, prefer app-bundled chunks or signed CI release manifests; hosted chunks must be first-party artifacts tied to the current release.

When to Load Reference Files

Load specific reference files from references/ based on the task:

JavaScript/React Performance (js-*)

  • Debugging slow/janky UI or animations → references/js-measure-fps.md
  • Investigating re-render issues → references/js-profile-react.md → references/js-react-compiler.md
  • Optimizing list scrolling → references/js-lists-flatlist-flashlist.md
  • Reducing re-renders with state management → references/js-atomic-state.md
  • Using Concurrent React features → references/js-concurrent-react.md
  • Enabling automatic memoization → references/js-react-compiler.md
  • Optimizing animations → references/js-animations-reanimated.md
  • Fixing TextInput lag → references/js-uncontrolled-components.md
  • Hunting JavaScript memory leaks → references/js-memory-leaks.md

Native Performance (native-*)

  • Measuring startup time (TTI) → references/native-measure-tti.md
  • Building native modules → references/native-turbo-modules.md
  • Understanding native threading → references/native-threading-model.md
  • Profiling native code → references/native-profiling.md
  • Setting up native tooling → references/native-platform-setup.md
  • Debugging view hierarchy → references/native-view-flattening.md
  • Native memory patterns → references/native-memory-patterns.md
  • Hunting native memory leaks → references/native-memory-leaks.md
  • Choosing native SDKs vs polyfills → references/native-sdks-over-polyfills.md
  • Fixing Android 16KB alignment → references/native-android-16kb-alignment.md

Bundle & App Size (bundle-*)

  • Analyzing bundle size → references/bundle-analyze-js.md
  • Analyzing app size → references/bundle-analyze-app.md
  • Fixing barrel imports → references/bundle-barrel-exports.md
  • Enabling tree shaking → references/bundle-tree-shaking.md
  • Android code shrinking → references/bundle-r8-android.md
  • Optimizing Hermes bundle loading → references/bundle-hermes-mmap.md
  • Managing native assets → references/bundle-native-assets.md
  • Evaluating library size → references/bundle-library-size.md
  • Code splitting → references/bundle-code-splitting.md

Problem → Reference Mapping

Use this quick lookup when debugging specific issues:

ProblemStart With
App feels slow/jankyreferences/js-measure-fps.md → references/js-profile-react.md
Too many re-rendersreferences/js-profile-react.md → references/js-react-compiler.md
Slow startup (TTI)references/native-measure-tti.md → references/bundle-analyze-js.md
Large app sizereferences/bundle-analyze-app.md → references/bundle-r8-android.md
Memory growingreferences/js-memory-leaks.md or references/native-memory-leaks.md
Animation drops framesreferences/js-animations-reanimated.md
List scroll jankreferences/js-lists-flatlist-flashlist.md
TextInput lagreferences/js-uncontrolled-components.md
Native module slowreferences/native-turbo-modules.md → references/native-threading-model.md
Native library alignment issuereferences/native-android-16kb-alignment.md

Quick Reference Commands

FPS & Re-renders

bash
agent-device react-devtools statusagent-device react-devtools wait --connectedagent-device react-devtools profile startagent-device react-devtools profile stopagent-device react-devtools profile slow --limit 5agent-device react-devtools profile rerenders --limit 5agent-device react-devtools profile timeline --limit 20

Drive the target interaction with normal agent-device commands between profile start and profile stop.

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.

For release-build React component profiling, connect @callstack/inspector first so React DevTools can attach to the release app, then run the agent-device react-devtools flow above.

Baseline runtime metrics should come from the target interaction itself:

  • Capture commit timeline, re-render counts, slow components, and heaviest-commit breakdown.
  • Treat component tree depth and count as supporting context only.

Common fixes:

  • Replace ScrollView with FlatList/FlashList for lists
  • After profiling shows cascading re-renders, use React Compiler for automatic memoization
  • After profiling shows broad store/context updates, use atomic state (Jotai/Zustand) to reduce re-renders
  • Use useDeferredValue for expensive computations

Review guardrails:

  • Check library versions before suggesting API-specific fixes. FlashList v2 deprecates estimatedItemSize.
  • Do not suggest useMemo or useCallback dependency changes without a reproducible correctness issue or profiling evidence.
  • Do not report stale closures unless the stale read path or repro is clear.

Analyze Bundle Size

bash
npx react-native bundle \  --entry-file index.js \  --bundle-output output.js \  --platform ios \  --sourcemap-output output.js.map \  --dev false --minify true
npx source-map-explorer output.js --no-border-checks

Common fixes:

  • Avoid barrel imports (import directly from source)
  • Remove unnecessary Intl polyfills only after checking Hermes API and method coverage
  • Evaluate tree shaking (Expo SDK 52+ experimental unused import/export removal, or Re.Pack only if already configured)
  • Enable R8 for Android native code shrinking

Measure TTI

  • Use react-native-performance for markers
  • Only measure cold starts (exclude warm/hot/prewarm)

Common fixes:

  • For React Native 0.78 and earlier, disable Android JS bundle compression to enable Hermes mmap
  • Use native navigation (react-native-screens)
  • Preload commonly-used expensive screens before navigating to them

Native Performance

Profile native:

  • iOS: Xcode Instruments → Time Profiler
  • Android: Android Studio → CPU Profiler

Common fixes:

  • Use background threads for heavy native work
  • Prefer async over sync Turbo Module methods
  • Use C++ for cross-platform performance-critical code

Priority Guidelines

Apply optimizations in this order:

PriorityCategoryImpactPrefix
1FPS & Re-rendersCRITICALjs-*
2Bundle SizeCRITICALbundle-*
3TTI OptimizationHIGHnative-*, bundle-*
4Native PerformanceHIGHnative-*
5Memory ManagementMEDIUM-HIGHjs-*, native-*
6AnimationsMEDIUMjs-*

Attribution

Based on "The Ultimate Guide to React Native Optimization" by Callstack.