Preface¶
Performance issues in React Native apps usually don’t stem from a single line of code. Stuttering lists, cold launches taking over two seconds, app bloat quietly caused by barrel imports, and memory leaks accumulating as users navigate between screens—these problems can occur simultaneously across the JS thread, native layers, and bundling pipeline. If you only rely on scattered blog posts, you might first tweak useMemo, then switch state libraries, only to find little to no improvement in frame rate or startup time.
Callstack first compiled this expertise into the human-facing ebook The Ultimate Guide to React Native Optimization, and in January 2026, they split it into an Agent Skill: react-native-best-practices. When loaded into AI coding tools like Cursor, Claude Code, or Codex, the assistant will reference targeted documentation in priority order during performance reviews or RN/Expo code changes, rather than generating generic advice based on vague impressions.
This article is organized after cross-checking the official repository, the original SKILL.md, and Callstack’s announcement: it explains what this Skill is, what issues it covers, how to install it, and how to actually use it in practice.
What It Is¶
react-native-best-practices is a React Native performance optimization guide designed for AI coding assistants. It is created by Callstack, hosted in the GitHub repository callstackincubator/agent-skills, and licensed under MIT.
It does not address tasks like “building a new screen”, but rather these types of work:
- Stuttering UI and dropped animation frames
- Rising JS or native memory usage over time
- Long TTI (Time to Interactive) cold startup
- Excessive JS bundle or app installation package size
- Writing and reviewing Turbo Modules
- Performing performance audits on existing React Native codebases
The Skill’s entry point is SKILL.md, with detailed steps in the references/ directory. The current SKILL.md lists 29 topic documents, grouped into three categories by prefix:
- js-*: JavaScript / React layer (lists, re-renders, animations, memory)
- native-*: iOS / Android native layers (TTI, threading, Turbo Modules, 16KB alignment)
- bundle-*: Bundling and size optimization (barrel exports, source-map-explorer, R8, Hermes mmap)
Callstack mapped these three categories to two core metrics in their announcement: FPS and TTI. The repository’s README also categorizes it under the Building React Native Apps plugin pack, to be installed alongside Skills for navigation, TV, library scaffolding, and upgrades.
Core Features¶
Measure First, Then Optimize¶
SKILL.md formalizes the optimization workflow as a fixed cycle: Measure → Optimize → Re-measure → Validate.
1. Measure: First establish a baseline. For runtime issues, prioritize commit timelines, re-render counts, slow components, the heaviest individual commit, and startup/TTI metrics. Component tree depth or total component counts should only be used as supplementary data, not primary evidence.
2. Optimize: Make targeted changes using the corresponding reference documents.
3. Re-measure: Run the same measurement workflow again.
4. Validate: Confirm that metrics have actually improved. The documentation uses these sample acceptance criteria: FPS 45→60, TTI 3.2s→1.8s, bundle size 2.1MB→1.6MB.
If metrics do not change, the documentation requires rolling back your changes and trying the next recommended fix. It also explicitly prohibits recommending memoization, atomic state, or enabling the React Compiler without first detecting re-render or FPS issues.
Prioritization Framework¶
| Priority | Category | Impact | Document Prefix |
|---|---|---|---|
| 1 | FPS & Re-renders | CRITICAL | js-* |
| 2 | App Bundle Size | CRITICAL | bundle-* |
| 3 | TTI | HIGH | native-*, bundle-* |
| 4 | Native Performance | HIGH | native-* |
| 5 | Memory | MEDIUM-HIGH | js-*, native-* |
| 6 | Animations | MEDIUM | js-* |
The impact labels are just for triage order: CRITICAL issues first, followed by HIGH, then MEDIUM issues only when supporting evidence is present.
Problem-to-Document Mapping¶
SKILL.md provides a problem lookup table, instructing assistants to reference files based on this table instead of loading all 29 documents into the context at once:
| Issue | Start With This Document |
|---|---|
| General stuttering | js-measure-fps.md → js-profile-react.md |
| Excessive re-renders | js-profile-react.md → js-react-compiler.md |
| Slow startup | native-measure-tti.md → bundle-analyze-js.md |
| Large installation package | bundle-analyze-app.md → bundle-r8-android.md |
| Rising memory usage | js-memory-leaks.md or native-memory-leaks.md |
| Dropped animation frames | js-animations-reanimated.md |
| Janky list scrolling | js-lists-flatlist-flashlist.md |
| TextInput lag | js-uncontrolled-components.md |
| Slow native modules | native-turbo-modules.md → native-threading-model.md |
| 16KB alignment issues with third-party libraries | native-android-16kb-alignment.md |
Installation and Activation¶
The official README points to the skills CLI for general installation, which works with Claude Code, Cursor, GitHub Copilot, Gemini CLI, OpenCode, and other compatible assistants. To install only this Skill:
npx skills@latest add callstackincubator/agent-skills --skill react-native-best-practices
The CLI will prompt you to select your target assistant and installation scope (project-level or user-level). The equivalent full repository URL syntax on officialskills.sh is:
npx skills add https://github.com/callstackincubator/agent-skills --skill react-native-best-practices
To install all Callstack Skills in the repository at once, replace --skill with '*'.
Differences for individual tools (refer to the current repository documentation for the latest details):
OpenAI Codex: Open Plugins, search for react native, and install the required plugin pack. This performance Skill is included in the Building React Native Apps pack.
Claude Code: In addition to the skills CLI above, the repository offers a marketplace. The three plugin packs in the current .claude-plugin/marketplace.json (version 1.2.0) are building-react-native-apps, testing-react-native-apps, and migrating-to-react-native. The performance-related Skills are in the first pack:
/plugin marketplace add callstackincubator/agent-skills
/plugin install building-react-native-apps@callstack-agent-skills
Note: Callstack’s January 2026 announcement previously mentioned installing react-native-best-practices@callstack-agent-skills as a standalone package. The current marketplace has switched to scenario-based packaging, and individual plugin names no longer appear in marketplace.json. Follow the repository’s current state when installing.
Cursor: The repository provides .mdc rules in .cursor/rules/, which you can import using Cursor’s Import rules from GitHub feature, pointing to https://github.com/callstackincubator/agent-skills.git. For full access to the documents, clone or copy the skills/ directory into your workspace. You can also directly ask the assistant to read the files in a conversation:
Read skills/react-native-best-practices/SKILL.md and help me optimize my FlatList performance
For assistants that do not support the skills CLI, the official AI Assistant Integration Guide covers manual setup for Cursor, Copilot, Claude Project Knowledge Bases, ChatGPT Custom GPT, Windsurf, and other tools.
Typical Usage¶
Once installed, you can describe tasks in natural language. The sample opening line from the repository README is:
Review this React Native screen for performance problems.
For more specific cases, share your code alongside the relevant reference document. The three examples below are from the official documentation and can be reproduced exactly.
1. Janky Lists: Replace ScrollView with Virtualized Lists¶
references/js-lists-flatlist-flashlist.md flags “putting long lists inside a ScrollView” as a CRITICAL issue. The incorrect pattern is rendering all items at once:
<ScrollView>
{items.map((item) => <Item key={item.id} {...item} />)}
</ScrollView>
The documentation recommends using FlashList (or FlatList / Legend List) instead:
<FlashList
data={items}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <Item {...item} />}
// FlashList v1 only: add estimatedItemSize.
// FlashList v2+: do not add estimated sizing props.
/>
There are two review constraints the Skill repeatedly emphasizes:
- First confirm the installed major version of FlashList. Version 1 requires estimatedItemSize, while this property and estimatedListSize/estimatedFirstItemOffset are deprecated as of v2 and later. Do not flag them as missing for newer versions.
- Continue using ScrollView for small, static content—do not replace all lists without first measuring performance.
In Cursor, you can reference files directly:
@MyListComponent.tsx
@skills/react-native-best-practices/references/js-lists-flatlist-flashlist.md
Migrate this component to use FlashList
2. Profile React Runtime Issues First¶
FPS and re-renders are marked as the highest priority. The recommended workflow uses React DevTools powered by agent-device:
agent-device react-devtools status
agent-device react-devtools wait --connected
agent-device react-devtools profile start
agent-device react-devtools profile stop
agent-device react-devtools profile slow --limit 5
agent-device react-devtools profile rerenders --limit 5
agent-device react-devtools profile timeline --limit 20
Between profile start and profile stop, run your target interaction using standard agent-device commands. If you do not have agent-device, the documentation provides a manual fallback: open React Native DevTools via Metro by pressing j or through the Dev Menu, and record the interaction using the Profiler tab. For release builds, you first need to connect with @callstack/inspector for React DevTools to attach to the release app.
After profiling, common fixes are listed in the Quick Reference section, but all have prerequisites:
- Long lists: Replace ScrollView with FlatList / FlashList / Legend List
- Cascading re-renders shown in profiling: Consider enabling the React Compiler
- Wide store/context updates shown in profiling: Consider atomic state libraries like Jotai / Zustand
- Expensive computations: Use useDeferredValue
Do not modify useMemo/useCallback dependencies or flag stale closures without profiling evidence.
3. Analyze Your JS Bundle Before Reducing Size¶
Bundle size is also marked as CRITICAL. First build a minified bundle, then use source-map-explorer to visualize dependency sizes:
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
After making changes, build another bundle with the same command and compare sizes using ls -lh output.js. The documentation uses a sample reduction from 2.1 MB to 1.6 MB. Common optimizations include: avoiding barrel imports, confirming Hermes is enabled before removing Intl polyfills, evaluating tree shaking (Expo SDK 52+ has experimental unused import removal, or Re.Pack if already integrated), and enabling R8 for Android.
The minimal R8 configuration is in references/bundle-r8-android.md:
// android/app/build.gradle
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true // Requires minifyEnabled
}
}
}
The documentation warns that standard React Native templates do not enable R8 by default; shrinkResources depends on minifyEnabled. Libraries with heavy reflection or code generation (such as Firebase) may require additional keep rules, and you must test changes using a release build. The sample size reduction in the documentation is 9.5 MB to 6.3 MB, about 33%; it also notes that larger apps typically see 20%–30% reductions. This is a guide example, not a guaranteed result for your specific project.
For TTI, the documentation requires only cold startup data (excluding warm/hot/prewarm launches) and recommends using react-native-performance for timing measurements. Common fixes include: disabling Android JS bundle compression for Hermes mmap on RN 0.78 and earlier, using react-native-screens for native navigation, and preloading frequently used heavy screens.
Use Cases and Important Notes¶
This Skill is a good fit for these people and scenarios:
- Maintaining a React Native or Expo app and troubleshooting stuttering, slow startup, large bundle sizes, or memory leaks
- Using AI assistants for RN code reviews and wanting them to follow Callstack’s triage order instead of suggesting memoization first
- Writing Turbo Modules and needing constraints for async interfaces and background threads
- Preparing for Google Play’s 16KB page alignment requirements and needing to audit third-party .so libraries
Keep these notes in mind, all taken directly from the official documentation:
1. This is not an auto-fixing tool. It provides decision frameworks, configuration steps, and reproducible measurement commands. As noted in Callstack’s announcement, visual tools like flame graphs and memory timelines are still difficult for agents to interpret directly, so the project’s near-term focus remains on practices that can be precisely described and consistently applied.
2. Read SKILL.md first, then open individual reference documents as needed. Loading all 29 documents at once wastes context and may lead you to apply MEDIUM-priority fixes too early.
3. Always verify library versions. FlashList v1 and v2 have conflicting requirements for estimatedItemSize; API-related fixes cannot be applied without matching your current dependency versions.
4. Treat commands as local development operations. The SKILL.md Security Notes require you to review shell scripts before running them, prioritize pinned tool versions, and never pipe remote scripts directly into your shell. Continue following standard supply chain management practices for third-party libraries, and only accept remote chunked loading for artifacts you control and tie to your current release.
5. Release and debug builds may behave differently. The announcement lists “inconsistent behavior between release and debug builds” as a common issue. Optimizations like R8, Hermes mmap, and resource compression must be validated on release builds.
6. Works well with agent-device. The integration guide notes: If you need to run workflows, take screenshots, or collect metrics on a real device or emulator, first check if the agent-device Skill is already available in your environment. If not and device validation is required, install it using the allowed method for your setup, otherwise fall back to your project’s existing manual validation workflow.
Summary¶
react-native-best-practices packages Callstack’s years of React Native performance work into a searchable handbook for AI agents: measure first, optimize in priority order of FPS, bundle size, TTI, native performance, memory, and animations, and map problems to specific documents using the js-*/native-*/bundle-* prefixes. For anyone using AI assistants to maintain React Native apps, it primarily solves the problem of “generic advice that doesn’t move the needle on actual metrics”.
Official links:
- Skill directory: https://github.com/callstackincubator/agent-skills/tree/main/skills/react-native-best-practices
- Repository overview and installation: https://github.com/callstackincubator/agent-skills
- Announcement: https://www.callstack.com/blog/announcing-react-native-best-practices-for-ai-agents
- Original ebook: https://www.callstack.com/ebooks/the-ultimate-guide-to-react-native-optimization