How to improve the performance of React Native applications?
Optimizing the performance of mobile applications is crucial for user satisfaction and product success. Even small delays can negatively affect the user experience, the popularity of the application, and its rating. React Native allows you to create cross-platform applications, but requires proper optimization to make them run fast and smoothly.W tym artykule znajdziesz praktyczne wskazówki oraz przykłady kodu, które pomogą ci skutecznie poprawić wydajność aplikacji React Native.

- 1. Diagnosing performance issues
- 2. Reduction of the number of unnecessary renders
- 3. Optimizing images
- 4. Managing long lists – why can long lists cause performance issues?
- 4.1. How can you optimize long lists in React Native?
- 4.2. Summary of long list optimizations in React Native:
- 5. Heavy calculations outside the main thread
- 6. Balancing animations between the JavaScript thread and the main thread
- 6.1. How to optimize animations in React Native?
- 6.2. InteractionManager
- 7. Data caching
- 8. Analyzing and reducing bundle size – why is bundle size important?
- 9. Test on real devices
- 10. How can AI help optimize React Native performance?
- 10.1. Several areas in which AI will help you optimize the performance of your React Native application:
- 10.1.1. Intelligent code analysis on an ongoing basis
- 10.1.2. Automatic bottleneck detection
- 10.1.3. Personalization of UX/UI based on user behavior analysis
- 10.1.4. Predictive resource management
- 10.1.5. Intelligent alerting about performance drops
React Native uses two separate threads: JavaScript Thread and Native UI Thread. Proper optimization should account for these differences, avoiding JavaScript thread overload and delegating as many tasks as possible to the native page.
1. Diagnosing performance issues
Before you start optimizing your mobile application, you need to know what is causing the problems. Tools such as Flipper, React Native Debugger, or Chrome DevTools will help you quickly identify problem areas. For example, Flipper offers a detailed overview of component rendering time, memory usage and web query analysis.
Also use React DevTools Profiler and Hermes profiler – especially if the application uses Hermes – to analyze memory usage, function execution time and sources of unnecessary rendering in more detail.
2. Reduction of the number of unnecessary renders
Avoid unnecessary component re-renders by using the following practices:
- use function components with React.memo and optional props comparison:
import React from 'react';
import { Text } from 'react-native';
const MyComponent = React.memo(({ name }) => <Text>{name}</Text>, (prev, next) => prev.name === next.name);- useCallback and useMemo, avoid anonymous functions in props:
import React, { useCallback } from 'react';
import { Button } from 'react-native';
const MyScreen = () => {
const handlePress = useCallback(() => {
console.log('Kliknięto!');
}, []);
return <Button onPress={handlePress} title="Kliknij mnie" />;
};In addition to React.memo or useCallback, remember to lift state up. Lifting state up means moving the state to a common parent component instead of keeping it locally in many smaller components of React Native. When the state is managed at a lower level (in many separate components), each change often causes multiple, unnecessary rerenders of child components. Moving the state up (to the parent component):
- allows you to effectively manage state changes and propagate it only where it is actually necessary.
- limits the number of components that react to changes (only those that really need access to the status are rendered),
- improves code readability and status management,
Example:
Instead of having local status in each list item, manage the status in the parent component (e.g. store selected itemsty w rodzicu, a nie osobno w każdym komponencie). Dzięki temu mniejsze komponenty będą rerenderowane tylko wtedy, kiedy zmieni się ich konkretny stan.
// Example lifting state up
const ParentComponent = () => {
const [selectedItem, setSelectedItem] = useState(null);
return (
<>
<ChildComponent
selected={selectedItem === 'item1'}
onSelect={() => setSelectedItem('item1')}
/>
<ChildComponent
selected={selectedItem === 'item2'}
onSelect={() => setSelectedItem('item2')}
/>
</>
);
};
3. Optimizing images
Images have a significant impact on the speed of an app. Always
- choose the right format (JPEG, PNG or WebP) for the type of image.
- use the react-native-fast-image library, which enables efficient caching:
import FastImage from 'react-native-fast-image';
const MyImage = () => (
<FastImage
source={{ uri: 'https://example.com/image.png' }}
resizeMode={FastImage.resizeMode.cover}
style={{ width: 200, height: 200 }}
/>
);4. Managing long lists – why can long lists cause performance issues?
Displaying a large number of items at the same time can negatively affect performance because:
- Each item rendered in React Native consumes CPU and RAM resources.
- Rendering multiple items at the same time leads to a long first render time and “lag” when scrolling through the list.
- An unoptimized list can lead to frequent re-renders of unnecessary elements.
How can you optimize long lists in React Native?
1. Use FlatList instead of ScrollView – FlatList is an optimized component built into React Native that only renders elements that are currently widoczne na ekranie. Przykład użycia FlatList:
<FlatList
data={data}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => <ListItem item={item} />}
/>
Advantages:
- Automatically renders only the elements visible on the screen (“windowing”).
- Saves memory and CPU time.
2. Implement unique keys (keyExtractor) – keys help React identify elements correctly and update the user interface efficiently. It is good practice to avoid using array indexes as keys, as they cause unnecessary re-renders when data changes. Example:
<FlatList
data={data}
keyExtractor={(item) => item.uniqueId}
/>
3. Use getItemLayout optimization – the getItemLayout – method allows FlatList to calculate the size of items faster, which affects rendering speed. Example:
<FlatList
data={data}
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
/>
4. Use PureComponent or React.memo to optimize list items – Each list item should be optimized separately to avoid unnecessary renders when scrolling. Example with React.memo:
const ListItem = React.memo(({ item }) => (
<View>
<Text>{item.name}</Text>
</View>
));
5. Limit the number of rendered elements (initialNumToRender) – the default values are often not optimal. You can adjust the FlatList parameters to your needs:
initialNumToRender– the number of elements rendered at the start.windowSize– the number of screens rendered out of view.
<FlatList
initialNumToRender={10}
windowSize={5}
/>
6. Optimize images in list items – use libraries for optimal image loading, e.g. react-native-fast-image instead of the standard Image Image component. Example:
import FastImage from 'react-native-fast-image';
<FastImage
style={{ width: 100, height: 100 }}
source={{
uri: 'https://example.com/image.png',
priority: FastImage.priority.normal,
}}
resizeMode={FastImage.resizeMode.cover}
/>
Summary of long list optimizations in React Native:
- Always use
FlatListorSectionList. - Use unique keys.
- Implement
getItemLayout. - Optimize list item components (
React.memo,PureComponent). - Manage FlatList properties (e.g.
initialNumToRender,windowSize). - Optimize images (
react-native-fast-image). - Use lazy loading of data for large amounts of information.
5. Heavy calculations outside the main thread
To avoid blocking the user interface:
- Use the InteractionManager to move operations to a time after the interactions:
import { InteractionManager } from 'react-native';
InteractionManager.runAfterInteractions(() => {
// Perform time-consuming operations
});6. Balancing animations between the JavaScript thread and the main thread
Animations in React Native can be handled by two main threads:
- JavaScript Thread – executes the application logic (calculations, state operations).
- UI (Main) Thread – handles rendering of the user interface.
By default, animations performed using the setState method are executed on the JavaScript thread, which can cause delays and performance drops, especially when JavaScript is heavily loaded with other tasks.
How to optimize animations in React Native?
Use native animations
React Native offers the Animated API, which allows you to move animations to a native thread. It is worth setting useNativeDriver: true, which will cause the animation to be performed outside the JavaScript thread:
Animated.timing(animationValue, {
toValue: 1,
duration: 300,
useNativeDriver: true,
}).start();
InteractionManager
Sometimes even native animations can be disrupted by intensive JavaScript logic. In this case, use InteractionManager.runAfterInteractions to postpone heavy calculations or data retrieval until after the animation has finished:
InteractionManager.runAfterInteractions(() => {
// Heavy operations, such as downloading data
});
7. Data caching
Reduce the number of server requests through effective data caching:
import { useQuery } from 'react-query';
const { data, isLoading } = useQuery('items', fetchItems, {
staleTime: 120000, // cache 2 minutes
});8. Analyzing and reducing bundle size – why is bundle size important?
How can I effectively analyze and reduce the bundle size in React Native? Below are the most important tips with examples:
1. React Native Bundle Visualizer
Use the react-native-bundle-visualizer library:
- It visualizes the size of each application module.
- It allows you to identify the largest libraries.
2. Use code splitting and dynamic imports – dynamic imports allow you to load application parts only when they are needed.
Example of a dynamic import:
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
const App = () => (
<Suspense fallback={<Text>Loading...</Text>}>
<LazyComponent />
</Suspense>
);
3. Remove unnecessary libraries and dead code – regularly verify library usage and remove unused modules. Use tools such as ESLint, which indicate unused code snippets.
4. Optimize multimedia resources – compress images using tools such as imagemin or TinyPNG. Choose optimized graphic formats: WebP or SVG.
5. Tree Shaking – make sure you use a bundler that supports tree shaking (e.g. Metro with the appropriate configuration, Hermes or additional tools, such as Metro bundler in production mode). Only import the elements you need:
// avoid this:
import _ from 'lodash';
// use:
import { isEmpty } from 'lodash';
9. Test on real devices
Always test performance on real devices, not just emulators or simulators. Only tests on physical devices provide reliable information about the real behavior of the application.
How can AI help optimize React Native performance?
How can AI really help detect performance problems? Here are some practical ways in which AI can really support the development of your React Native application:
Example situation: You notice a slowdown in your application, but you don’t know where the problem is. Just paste a piece of code into an AI-based tool (e.g. chatGPT) with the prompt:
“Show which parts of the following React Native code can cause performance issues and suggest improvements.”
Other example prompts you can use:
“How can I implement predictive data loading in my React Native app to improve the loading speed for users?”
“Based on the following package.json file and the structure of my React Native project, what changes can I make to effectively reduce the size of the application package?”
Several areas in which AI will help you optimize the performance of your React Native application:
1. Intelligent code analysis on an ongoing basis
AI can analyze your React Native code on an ongoing basis and immediately suggest improvements, point out performance problems, or eliminate unnecessary component rendering.
2. Automatic bottleneck detection
By monitoring application performance in real time, AI tools can quickly identify the points of highest load and provide recommendations for resolving them.
3. Personalization of UX/UI based on user behavior analysis
AI analyzes the behavior of application users, suggesting interface and functionality adjustments to make the application faster and more intuitive.
4. Predictive resource management
AI can predict which resources (images, data, components) the user will need next, so the application can load them in advance and thus increase its responsiveness.
5. Intelligent alerting about performance drops
AI can dynamically identify unusual application behavior, automatically sending notifications to the development team, allowing for a quick response and minimizing the effects of problems.


