8 React Native Performance Mistakes That Slow Down Your App
Common React Native performance mistakes that cause slow renders, dropped frames, and high memory usage — and how to fix each one correctly.
Most React Native performance problems are not caused by the framework. They are caused by a small set of implementation patterns that appear reasonable but compound badly as the app grows. Identifying these early saves significant time later.
Here are the eight most common React Native performance mistakes and the practical fix for each.
1. Running Animations on the JavaScript Thread
The JavaScript thread in React Native handles your app's business logic, state updates, and component re-renders. It is a single thread. When you run an animation on the JS thread, every frame of that animation competes with everything else your app is doing.
The mistake looks like this:
// Incorrect — JS thread driven
Animated.timing(opacity, {
toValue: 1,
duration: 300,
useNativeDriver: false, // the problem
}).start();Set useNativeDriver: true for any animation on transform or opacity properties. This offloads the animation to the UI thread, which runs independently of the JS thread. For gesture-driven animations and more complex sequences, use Reanimated 3, which runs worklets on the UI thread using JSI.
2. Re-rendering Components That Do Not Need to Update
A component that re-renders unnecessarily is the most common React Native performance problem. It happens when:
- A parent component re-renders and passes a new object or function reference to a child that did not actually change
- State is stored too high in the component tree and every state change re-renders a large subtree
- Context is used for frequently-changing values, causing every context consumer to re-render
The fixes are straightforward:
- Wrap stable components in
React.memo - Stabilize function references with
useCallback - Stabilize object references with
useMemo - Split context into small, focused providers so consumers only subscribe to what they need
- Move state as close as possible to where it is consumed
Before applying useMemo or useCallback everywhere, profile first. These hooks have a cost. Apply them where measurements show a re-render problem, not speculatively.
3. Loading Too Much Data Into a Single List
Loading 500+ items into a FlatList and expecting virtualization to handle everything is a common mistake. Virtualization reduces the number of rendered items, but it does not reduce the size of the data array held in memory or the JavaScript work done to manage it.
The fix is server-side or API-level pagination. Fetch 20-30 items at a time and load more as the user approaches the end of the list via onEndReached. The total item count in your state should grow incrementally, not be loaded in full on mount.
4. Not Using getItemLayout on Fixed-Height Lists
Without getItemLayout, FlatList measures every item as it enters the viewport to determine its height. This measurement runs on the UI thread and causes stuttering on scroll.
If your list items have a fixed height, implement getItemLayout to provide the height and offset for each index directly. This eliminates the measurement pass entirely and is one of the highest-return optimizations available.
5. Storing Large Data Structures in useState or Redux
Storing arrays of thousands of objects in React state causes slow re-renders any time that state updates, because React has to diff and reconcile the component tree for every change. It also causes slow serialization if you are persisting state with redux-persist or AsyncStorage.
For large local datasets, use a proper on-device database. WatermelonDB and MMKV are the standard choices for React Native in 2026. WatermelonDB is optimized for relational data with lazy loading. MMKV is an extremely fast key-value store for smaller, frequently-accessed data.
6. Blocking the Main Thread with Synchronous Operations
Reading large files, parsing JSON responses, or running complex calculations synchronously on the JS thread blocks UI interaction. Users cannot tap, scroll, or see animations while synchronous work is executing.
Move heavy computation off the main thread. Options:
- Use the Hermes engine's built-in support for background tasks where available
- Offload to a native module that runs on a background thread
- Decompose large calculations into smaller chunks using
requestAnimationFrameorInteractionManager.runAfterInteractionsto yield between batches
For persistent background work (sync, uploads, push processing), use native background processing APIs via an appropriate React Native library rather than attempting to keep the JS thread alive.
7. Using Images Without Size Constraints
React Native has to measure every image to determine its layout dimensions if width and height are not specified. This triggers an additional layout pass. At scale — a feed with many images — this causes cumulative layout performance problems.
Always specify explicit width and height on Image components, or use flex with a known aspect ratio. Use react-native-fast-image for remote images to get persistent disk caching and avoid re-fetching images that have already been loaded.
8. Ignoring the JS Bundle Size
A large JavaScript bundle is a slow app startup. Every kilobyte of JS has to be read from disk, parsed, and compiled by Hermes before your first screen renders. This is especially painful on lower-end Android devices.
Common sources of bundle bloat:
- Importing an entire utility library when you only use one function (lodash is the classic example)
- Bundling large static assets (PDFs, data files) inside the JS bundle instead of reading them from the filesystem at runtime
- Shipping multiple versions of the same library because of nested dependency mismatches
Use the Metro bundle analyzer to identify the largest modules in your bundle. Fix them in order of size.
These eight mistakes account for the majority of React Native performance problems we see in production apps. The common thread is that each problem is measurable — profile first, fix the metric, confirm the improvement.
If your team is working through a performance project or building a performance-sensitive product from scratch, reach out to Clixo. We ship React Native products and have the profiling and optimization process down to a repeatable discipline.