React Native Prestandaoptimering 2026: Från New Architecture till React Compiler
React Native har förändrats enormt de senaste åren — och jag menar verkligen enormt. Den nya arkitekturen är nu obligatorisk sedan version 0.78, React Compiler v1.0 tar hand om memoization åt dig, och Hermes är standardmotor. Ekosystemet har mognat till en punkt där prestanda inte längre är något du kompromissar med. Det är en grundpelare.
I den här guiden går vi igenom allt du behöver veta om prestandaoptimering i React Native 2026, från arkitekturnivå ner till enskilda komponentoptimeringar. Oavsett om du bygger en helt ny app eller migrerar en befintlig kodbas hittar du konkreta verktyg, kodexempel och strategier här.
Målet? 60fps-renderingar, snabba kallstarter och minimal minnesanvändning. Så, låt oss köra.
Varför prestanda spelar roll mer än någonsin
Användarnas förväntningar på mobilappar har helt enkelt aldrig varit högre. Studier visar att 53% av användarna överger en app som tar längre än 3 sekunder att ladda. Redan en fördröjning på 100ms i interaktionsrespons upplevs som tröghet. Det låter kanske hårt, men det är verkligheten.
React Native-appar konkurrerar direkt med nativa appar byggda i Swift och Kotlin. Marginalen för vad som upplevs som "acceptabel prestanda" har krympt rejält.
Den största förändringen? React Natives nya arkitektur är nu obligatorisk. Sedan version 0.78 finns det gamla bridge-baserade systemet helt enkelt inte kvar som alternativ. Alla React Native-utvecklare måste förstå och utnyttja JSI, Fabric-renderaren och TurboModules för att bygga performanta appar.
Samtidigt har React 19 och React Compiler introducerat fundamentala förändringar. Concurrent rendering, automatisk memoization och nya hooks som useTransition förändrar spelplanen helt. Utvecklare som lär sig de här verktygen kan bygga appar som känns precis lika snabba som fullt nativa lösningar.
New Architecture: Prestandafördelarna i praktiken
JSI ersätter Bridge
Det gamla bridge-systemet serialiserade all kommunikation mellan JavaScript och native-sidan som JSON-meddelanden via en asynkron kö. Det skapade flaskhalsar, särskilt vid frekventa uppdateringar som animationer och scrollning.
JSI (JavaScript Interface) ersätter allt det med direkt minnesdelning mellan JavaScript och native-kod. Med JSI kan JavaScript anropa native-funktioner synkront — ingen serialisering, nästintill noll latens.
I praktiken innebär det här:
- Cirka 40% snabbare kallstarter tack vare att bridge-initialisering försvinner och moduler laddas lat
- 20-30% lägre minnesanvändning genom att data inte längre dupliceras mellan JavaScript och native-minnet
- Konsekvent 60fps vid komplexa animationer och scrollning, tack vare synkron kommunikation
Ärligt talat, den skillnaden märks direkt.
Fabric Renderer
Fabric är den nya renderingsmotorn som ersätter det gamla UI Manager-systemet. Den möjliggör synkron rendering direkt på UI-tråden, stödjer concurrent rendering och ger bättre kontroll över layoutberäkningar.
// react-native.config.js — Fabric är aktiverat som standard sedan 0.78
// men du kan verifiera konfigurationen:
module.exports = {
project: {
ios: {
automaticPodsInstallation: true,
},
android: {
// Fabric och TurboModules aktiveras automatiskt
},
},
};
TurboModules och Lazy Loading
TurboModules ersätter det gamla NativeModules-systemet och introducerar lazy loading — moduler laddas först när de faktiskt behövs istället för vid appstart. Effekten på kallstarttider är dramatisk.
// Exempel: TurboModule med lazy loading
// Modulen laddas inte förrän första anropet
import { TurboModuleRegistry } from 'react-native';
// Typ-säker åtkomst till native-modul
// Modulen initialiseras först vid getEnforcing()-anropet
const CameraModule = TurboModuleRegistry.getEnforcing('CameraModule');
// Alternativt: valfri åtkomst (returnerar null om modulen inte finns)
const OptionalModule = TurboModuleRegistry.get('OptionalModule');
// Användning i en komponent
export function useCameraPermission() {
const [hasPermission, setHasPermission] = useState(false);
useEffect(() => {
// CameraModule laddas in först här, vid behov
CameraModule.requestPermission().then(granted => {
setHasPermission(granted);
});
}, []);
return hasPermission;
}
Bridgeless Mode
Bridgeless mode tar bort den gamla bridge-infrastrukturen helt — inklusive alla kompatibilitetslager. Det frigör ytterligare minne och förenklar arkitekturen internt. Sedan React Native 0.78 körs alla appar i bridgeless mode som standard, så det finns inget du behöver konfigurera.
React Compiler och automatisk memoization
Det här är (enligt mig) en av de mest spännande förändringarna 2026. React Compiler v1.0 analyserar din React-kod vid byggtid och infogar automatiskt memoization där det behövs. I praktiken betyder det att du inte längre behöver skriva useMemo, useCallback eller React.memo manuellt i de allra flesta fall.
Ja, du läste rätt. Manuell memoization är i princip historia.
Aktivera React Compiler
// babel.config.js — Aktivera React Compiler
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
['babel-plugin-react-compiler', {
target: '19',
runtimeModule: 'react/compiler-runtime',
}],
],
};
Före och efter: Manuell vs automatisk memoization
Så här ser skillnaden ut i praktiken:
// FÖRE: Manuell memoization (gammal stil)
import React, { useMemo, useCallback, memo } from 'react';
const ProductCard = memo(({ product, onPress }) => {
const formattedPrice = useMemo(() => {
return new Intl.NumberFormat('sv-SE', {
style: 'currency',
currency: 'SEK',
}).format(product.price);
}, [product.price]);
const handlePress = useCallback(() => {
onPress(product.id);
}, [onPress, product.id]);
const availableSizes = useMemo(() => {
return product.sizes.filter(size => size.inStock);
}, [product.sizes]);
return (
<Pressable onPress={handlePress}>
<Text>{product.name}</Text>
<Text>{formattedPrice}</Text>
{availableSizes.map(size => (
<Text key={size.id}>{size.label}</Text>
))}
</Pressable>
);
});
// EFTER: Med React Compiler (2026-stil)
// Kompilatorn hanterar ALL memoization automatiskt!
function ProductCard({ product, onPress }) {
const formattedPrice = new Intl.NumberFormat('sv-SE', {
style: 'currency',
currency: 'SEK',
}).format(product.price);
const handlePress = () => {
onPress(product.id);
};
const availableSizes = product.sizes.filter(size => size.inStock);
return (
<Pressable onPress={handlePress}>
<Text>{product.name}</Text>
<Text>{formattedPrice}</Text>
{availableSizes.map(size => (
<Text key={size.id}>{size.label}</Text>
))}
</Pressable>
);
}
Resultaten talar för sig själva. Företag som migrerat till React Compiler rapporterar 20-30% kortare rendertider i genomsnitt, och vissa komplexa vyer ser upp till 50% förbättring. Det bästa? Det sker utan att du behöver tänka på optimering — kompilatorn gör jobbet åt dig.
Vad kompilatorn inte hanterar
React Compiler är dock ingen silverkula. Du behöver fortfarande tänka på:
- Datastrukturdesign — kompilatorn kan inte trolla bort dåligt designade dataflöden
- Nätverksanrop — asynkrona operationer måste fortfarande hanteras korrekt
- Native-modulinteraktion — optimering av native-anrop ligger utanför kompilatorns räckvidd
- Listrenderingsstrategier — valet av rätt listkomponent är fortfarande ditt ansvar
Listrendering: FlatList vs FlashList v2 vs Legend List
Listrendering är en av de vanligaste prestandaflaskhalsarna i React Native-appar. Och det är inte så konstigt — listor kan innehålla hundratals eller tusentals element. 2026 finns det tre huvudalternativ att välja mellan.
FlatList — standardvalet
// FlatList med alla viktiga optimeringar
import { FlatList } from 'react-native';
function OptimizedFlatList({ data }) {
const getItemLayout = (data, index) => ({
length: 80,
offset: 80 * index,
index,
});
const keyExtractor = (item) => item.id.toString();
const renderItem = ({ item }) => (
<View style={styles.row}>
<Text>{item.title}</Text>
<Text>{item.subtitle}</Text>
</View>
);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
getItemLayout={getItemLayout}
removeClippedSubviews={true}
initialNumToRender={10}
maxToRenderPerBatch={5}
windowSize={5}
updateCellsBatchingPeriod={50}
/>
);
}
FlashList v2 — den prestandaoptimerade lösningen
FlashList v2 från Shopify har blivit det föredragna valet för de flesta React Native-appar 2026. Den stora nyheten i v2 är pixel-perfekt scrollning utan storleksuppskattningar — du behöver inte ange estimatedItemSize längre. Det är en av de där förändringarna som bara gör livet enklare.
// FlashList v2 — pixel-perfekt scrollning
import { FlashList } from '@shopify/flash-list';
function OptimizedFlashList({ data }) {
const renderItem = ({ item }) => (
<View style={styles.row}>
<Image source={{ uri: item.image }} style={styles.thumbnail} />
<View style={styles.content}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.description}>{item.description}</Text>
</View>
</View>
);
return (
<FlashList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
drawDistance={250}
/>
);
}
Legend List — det nya alternativet
Legend List är ett relativt nytt alternativ som fokuserar på enkelhet och prestanda med minimal konfiguration. Värt att hålla ögonen på.
// Legend List — minimalistisk men kraftfull
import { LegendList } from '@legendapp/list';
function OptimizedLegendList({ data }) {
return (
<LegendList
data={data}
renderItem={({ item }) => (
<View style={styles.row}>
<Text>{item.title}</Text>
</View>
)}
keyExtractor={(item) => item.id}
recycleItems={true}
estimatedItemSize={72}
/>
);
}
Jämförelse och rekommendationer
- FlatList: Fungerar bra för enkla listor med färre än 100 element, men kräver mest manuell optimering.
- FlashList v2: Det rekommenderade valet för de flesta appar 2026. Bäst prestanda med minimal konfiguration.
- Legend List: Ett bra alternativ om du redan använder Legend State. Enkel API-yta med solid prestanda.
Animationsprestanda
Animationer är ofta det första användaren reagerar på (ursäkta ordvitsen). En animation som inte håller 60fps upplevs direkt som hackig och oprofessionell. Lyckligtvis finns det flera bra strategier för smidiga animationer i React Native 2026.
Reanimated med Worklets på UI-tråden
React Native Reanimated kör animationslogik direkt på UI-tråden via worklets, helt oberoende av JavaScript-tråden. Det garanterar 60fps även när JS-tråden är fullt upptagen med annat.
// Reanimated — animationer på UI-tråden
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
interpolate,
Extrapolation,
} from 'react-native-reanimated';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
function AnimatedCard() {
const scale = useSharedValue(1);
const translateY = useSharedValue(0);
const opacity = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({
transform: [
{ scale: scale.value },
{ translateY: translateY.value },
],
opacity: opacity.value,
}));
const tapGesture = Gesture.Tap()
.onBegin(() => {
scale.value = withSpring(0.95, {
damping: 15,
stiffness: 150,
});
})
.onFinalize(() => {
scale.value = withSpring(1, {
damping: 15,
stiffness: 150,
});
});
return (
<GestureDetector gesture={tapGesture}>
<Animated.View style={[styles.card, animatedStyle]}>
<Text>Tryck på mig!</Text>
</Animated.View>
</GestureDetector>
);
}
Native Driver-animationer
För enklare animationer kan du använda React Natives inbyggda Animated API med useNativeDriver: true. Dessa animationer körs helt på native-sidan, vilket gör dem riktigt snabba.
// Native driver-animation — enkel och effektiv
import { Animated, Easing } from 'react-native';
function FadeInView({ children }) {
const fadeAnim = useRef(new Animated.Value(0)).current;
const slideAnim = useRef(new Animated.Value(50)).current;
useEffect(() => {
Animated.parallel([
Animated.timing(fadeAnim, {
toValue: 1,
duration: 400,
easing: Easing.out(Easing.cubic),
useNativeDriver: true,
}),
Animated.timing(slideAnim, {
toValue: 0,
duration: 400,
easing: Easing.out(Easing.cubic),
useNativeDriver: true,
}),
]).start();
}, []);
return (
<Animated.View
style={{
opacity: fadeAnim,
transform: [{ translateY: slideAnim }],
}}
>
{children}
</Animated.View>
);
}
LayoutAnimation för enkla layoutändringar
Om du bara behöver animera en expandering eller kollapsen av en sektion kan LayoutAnimation vara tillräckligt. Det är otroligt enkelt att implementera.
// LayoutAnimation — animera layoutförändringar automatiskt
import { LayoutAnimation, Platform, UIManager } from 'react-native';
if (Platform.OS === 'android' &&
UIManager.setLayoutAnimationEnabledExperimental) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
function ExpandableSection({ title, children }) {
const [expanded, setExpanded] = useState(false);
const toggleExpanded = () => {
LayoutAnimation.configureNext(
LayoutAnimation.Presets.easeInEaseOut
);
setExpanded(!expanded);
};
return (
<View>
<Pressable onPress={toggleExpanded}>
<Text>{title}</Text>
</Pressable>
{expanded && (
<View style={styles.content}>
{children}
</View>
)}
</View>
);
}
useTransition och Concurrent Features
React 19:s concurrent features är nu fullt tillgängliga i React Native tack vare Fabric-renderaren. Den kanske viktigaste funktionen för prestanda är useTransition, som låter dig markera uppdateringar som icke-brådskande. Resultatet? Användargränssnittet förblir responsivt även under tunga beräkningar.
Praktiskt exempel: Sökfiltrering
Här är ett konkret exempel som visar hur du kan filtrera en produktlista utan att sökfältet laggar:
// useTransition — icke-blockerande UI-uppdateringar
import { useState, useTransition } from 'react';
import { TextInput, View, Text, ActivityIndicator } from 'react-native';
function ProductSearch({ products }) {
const [query, setQuery] = useState('');
const [filteredProducts, setFilteredProducts] = useState(products);
const [isPending, startTransition] = useTransition();
const handleSearch = (text) => {
// Omedelbar uppdatering — användaren ser sina tangenter direkt
setQuery(text);
// Icke-brådskande uppdatering — kan avbrytas om användaren
// fortsätter skriva
startTransition(() => {
const filtered = products.filter(product => {
const searchLower = text.toLowerCase();
return (
product.name.toLowerCase().includes(searchLower) ||
product.description.toLowerCase().includes(searchLower) ||
product.category.toLowerCase().includes(searchLower)
);
});
setFilteredProducts(filtered);
});
};
return (
<View style={styles.container}>
<TextInput
value={query}
onChangeText={handleSearch}
placeholder="Sök produkter..."
style={styles.searchInput}
/>
{isPending && (
<View style={styles.loadingOverlay}>
<ActivityIndicator size="small" color="#007AFF" />
<Text style={styles.loadingText}>Filtrerar...</Text>
</View>
)}
<FlashList
data={filteredProducts}
renderItem={({ item }) => <ProductCard product={item} />}
keyExtractor={(item) => item.id}
extraData={isPending}
/>
</View>
);
}
Kombinera useTransition med tung beräkning
// Avancerat: useTransition med tung databearbetning
import { useState, useTransition, useDeferredValue } from 'react';
function AnalyticsDashboard({ rawData }) {
const [timeRange, setTimeRange] = useState('week');
const [isPending, startTransition] = useTransition();
const [processedData, setProcessedData] = useState(null);
const deferredData = useDeferredValue(processedData);
const handleTimeRangeChange = (range) => {
setTimeRange(range);
startTransition(() => {
const processed = processAnalyticsData(rawData, range);
setProcessedData(processed);
});
};
return (
<View>
<SegmentedControl
values={['Dag', 'Vecka', 'Månad', 'År']}
selectedIndex={['day', 'week', 'month', 'year'].indexOf(timeRange)}
onChange={(e) => {
const ranges = ['day', 'week', 'month', 'year'];
handleTimeRangeChange(ranges[e.nativeEvent.selectedSegmentIndex]);
}}
/>
<View style={{ opacity: isPending ? 0.7 : 1 }}>
<AnalyticsChart data={deferredData} />
</View>
</View>
);
}
Med useTransition kan användaren navigera, scrolla och interagera med appen medan tunga beräkningar pågår i bakgrunden. React avbryter automatiskt lågprioriterade renderingar om en högprioriterad uppdatering (som en knapptryckning) kommer in. Det är riktigt elegant.
Bildoptimering
Bilder är ofta den enskilt största resursen i en mobilapp. En enda ooptimerad bild kan förstöra din starttid och äta upp minnet. Här är vad du bör göra.
expo-image — den rekommenderade lösningen
// expo-image — avancerad bildhantering med inbyggd cachning
import { Image } from 'expo-image';
const blurhash = 'LEHV6nWB2yk8pyo0adR*.7kCMdnj';
function OptimizedImage({ uri, width, height }) {
return (
<Image
source={{ uri }}
style={{ width, height }}
placeholder={{ blurhash }}
transition={200}
cachePolicy="memory-disk"
contentFit="cover"
priority="normal"
recyclingKey={uri}
/>
);
}
// Förladda bilder för snabbare visning
import { Image as ExpoImage } from 'expo-image';
async function preloadImages(imageUrls) {
await Promise.all(
imageUrls.map(url => ExpoImage.prefetch(url))
);
}
WebP-format och bildstorlekar
WebP erbjuder 25-34% bättre komprimering jämfört med JPEG vid likvärdig kvalitet. Alla moderna enheter stöder WebP, och det bör vara standardformatet för bilder i din app. Det finns egentligen ingen anledning att inte använda det.
// Dynamiska bildstorlekar baserat på enhetens skärm
import { PixelRatio, Dimensions } from 'react-native';
function getOptimizedImageUrl(baseUrl, displayWidth) {
const pixelWidth = PixelRatio.getPixelSizeForLayoutSize(displayWidth);
const sizes = [200, 400, 600, 800, 1200, 1600];
const optimalSize = sizes.find(s => s >= pixelWidth) || sizes[sizes.length - 1];
return `${baseUrl}?w=${optimalSize}&format=webp&q=80`;
}
SVG-ikoner istället för rasterbilder
// SVG-ikoner — skalbar grafik utan kvalitetsförlust
import Svg, { Path } from 'react-native-svg';
function ChevronIcon({ size = 24, color = '#333' }) {
return (
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
<Path
d="M9 18l6-6-6-6"
stroke={color}
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
/>
</Svg>
);
}
Hermes-profilering och prestandamätning
Att mäta prestanda är lika viktigt som att optimera den. Utan mätdata optimerar du i blindo — och det är ett recept för att slösa tid på fel saker. Hermes-motorn har kraftfulla profileringsverktyg som hjälper dig hitta de faktiska flaskhalsarna.
Hermes-profilering
// Starta Hermes-profileraren programmatiskt
function startProfiling() {
if (global.HermesInternal) {
global.HermesInternal.enableSampling();
console.log('Hermes-profilering startad');
}
}
async function stopProfiling() {
if (global.HermesInternal) {
global.HermesInternal.disableSampling();
const profilePath = await global.HermesInternal.dumpSampledTraceToFile();
console.log('Profil sparad till:', profilePath);
}
}
react-native-release-profiler
Det här verktyget möjliggör profilering i release-byggen, vilket ger mycket mer realistiska prestandadata jämfört med development-byggen.
// Profilering i release-byggen
import {
startProfiling,
stopProfiling,
} from 'react-native-release-profiler';
async function profileUserFlow(flowName) {
startProfiling();
// Utför det flöde du vill mäta
const result = await stopProfiling(true);
console.log(`Profil för ${flowName}:`, result);
await uploadProfile(flowName, result);
}
Prestandamätning med Performance API
// Mät renderingstid för specifika komponenter
function useRenderTimer(componentName) {
useEffect(() => {
const startTime = performance.now();
return () => {
const endTime = performance.now();
const renderTime = endTime - startTime;
if (renderTime > 16.67) {
console.warn(
`${componentName} renderingstid: ${renderTime.toFixed(2)}ms ` +
`(överstiger 16.67ms för 60fps)`
);
}
};
});
}
Sentry-profilering i produktion
För appar i produktion är Sentry Performance Monitoring ovärderligt. Du kan spåra transaktioner, mäta specifika spans och identifiera flaskhalsar som bara uppstår med riktiga användare.
// Sentry Performance Monitoring
import * as Sentry from '@sentry/react-native';
Sentry.init({
dsn: 'https://[email protected]/0',
tracesSampleRate: 0.2,
profilesSampleRate: 0.1,
enableAutoPerformanceTracing: true,
});
function CheckoutScreen() {
useEffect(() => {
const transaction = Sentry.startTransaction({
name: 'checkout-flow',
op: 'navigation',
});
const loadSpan = transaction.startChild({
op: 'data.load',
description: 'Ladda kundvagnsdata',
});
fetchCartData().then(() => {
loadSpan.finish();
const renderSpan = transaction.startChild({
op: 'ui.render',
description: 'Rendera kassasidan',
});
requestAnimationFrame(() => {
renderSpan.finish();
transaction.finish();
});
});
}, []);
return <CheckoutForm />;
}
Tillståndshantering och prestanda
Hur du hanterar tillstånd påverkar renderingsprestanda direkt. Varje tillståndsuppdatering triggar potentiellt omrenderingar, och hur tillståndet är strukturerat avgör vilka komponenter som drabbas.
Context API, Redux Toolkit och Zustand — en jämförelse
Context API har ett välkänt problem: varje uppdatering av ett Context-värde orsakar omrendering av alla konsumenter, oavsett om de använder den ändrade datan eller inte. Det gör Context olämpligt för tillstånd som uppdateras ofta.
Redux Toolkit löser det med selectors som ger finkornig kontroll, men det medför mer boilerplate och komplexitet.
Zustand har blivit det rekommenderade valet 2026 för de flesta React Native-appar. Minimal API-yta, inbyggt selector-stöd och utmärkt prestanda. Kort sagt: det gör jobbet utan att komplicera saker.
Zustand — praktiskt exempel
// Zustand store — minimal boilerplate, maximal prestanda
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
const useAppStore = create(
immer((set, get) => ({
products: [],
cart: [],
user: null,
isLoading: false,
addToCart: (product) =>
set((state) => {
const existing = state.cart.find(item => item.id === product.id);
if (existing) {
existing.quantity += 1;
} else {
state.cart.push({ ...product, quantity: 1 });
}
}),
removeFromCart: (productId) =>
set((state) => {
state.cart = state.cart.filter(item => item.id !== productId);
}),
fetchProducts: async () => {
set({ isLoading: true });
try {
const response = await fetch('https://api.example.com/products');
const products = await response.json();
set({ products, isLoading: false });
} catch (error) {
set({ isLoading: false });
}
},
}))
);
// VIKTIGT: Använd selectors för att minimera omrenderingar!
function CartBadge() {
const cartCount = useAppStore(
(state) => state.cart.reduce((sum, item) => sum + item.quantity, 0)
);
return (
<View style={styles.badge}>
<Text style={styles.badgeText}>{cartCount}</Text>
</View>
);
}
function ProductList() {
const products = useAppStore((state) => state.products);
const isLoading = useAppStore((state) => state.isLoading);
const fetchProducts = useAppStore((state) => state.fetchProducts);
useEffect(() => { fetchProducts(); }, []);
if (isLoading) return <ActivityIndicator />;
return (
<FlashList
data={products}
renderItem={({ item }) => <ProductCard product={item} />}
keyExtractor={(item) => item.id}
/>
);
}
Undvik vanliga tillståndsmisstag
Det här är något jag ser gång på gång i kodgranskningar — och det kan göra enorm skillnad:
// DÅLIGT: Prenumerera på hela store
function BadComponent() {
const store = useAppStore(); // Omrenderas vid VARJE ändring!
return <Text>{store.user?.name}</Text>;
}
// BRA: Prenumerera bara på det du behöver
function GoodComponent() {
const userName = useAppStore((state) => state.user?.name);
return <Text>{userName}</Text>;
}
// BRA: Använd shallow-jämförelse för objekt
import { shallow } from 'zustand/shallow';
function CartSummary() {
const { totalItems, totalPrice } = useAppStore(
(state) => ({
totalItems: state.cart.reduce((s, i) => s + i.quantity, 0),
totalPrice: state.cart.reduce((s, i) => s + i.price * i.quantity, 0),
}),
shallow
);
return (
<View>
<Text>Antal: {totalItems}</Text>
<Text>Totalt: {totalPrice.toFixed(2)} kr</Text>
</View>
);
}
Praktisk checklista för React Native-prestanda 2026
Här kommer en sammanfattande checklista med alla optimeringar vi gått igenom. Bokmärk gärna den här och använd den vid utveckling och kodgranskning.
Arkitektur och byggsystem
- Verifiera att nya arkitekturen är aktiv — Fabric, JSI och TurboModules ska vara aktiverade (standard sedan 0.78)
- Aktivera React Compiler — lägg till
babel-plugin-react-compileri din Babel-konfiguration - Använd Hermes — säkerställ att Hermes är JavaScript-motorn (standard sedan 0.70)
- Konfigurera ProGuard/R8 (Android) — minifiera och optimera native-koden i release-byggen
Rendering och komponenter
- Använd FlashList v2 istället för FlatList — pixel-perfekt scrollning utan storleksuppskattningar
- Implementera useTransition för tunga uppdateringar — håll UI responsivt under databearbetning
- Använd useDeferredValue för uppskjuten rendering — låt React prioritera användarinteraktioner
- Minimera komponentdjup — plattare komponentträd renderas snabbare
- Undvik inline-objekt i rendermetoder — skapa stilar och konfigurationsobjekt utanför komponenter
Bilder och media
- Använd expo-image istället för React Natives Image — bättre cachning, blurhash-stöd och WebP-kompatibilitet
- Servera bilder i WebP-format — 25-34% bättre komprimering
- Anpassa bildstorlek till enheten — använd PixelRatio för att begära rätt storlek
- Förladda kritiska bilder — använd Image.prefetch() för bilder som visas direkt
- Använd SVG för ikoner och enkel grafik — skalas perfekt med liten filstorlek
Animationer
- Använd Reanimated för komplexa animationer — worklets körs på UI-tråden och garanterar 60fps
- Aktivera useNativeDriver för Animated API — offloadar animationer till native-tråden
- Använd LayoutAnimation för enkla layoutändringar — automatisk animation utan manuell styrning
- Undvik animering av layout-egenskaper — transform och opacity är billigast att animera
Tillståndshantering
- Välj Zustand framför Context API — undviker onödiga omrenderingar vid frekvent uppdaterat tillstånd
- Använd alltid selectors — prenumerera bara på den data komponenten faktiskt behöver
- Använd shallow-jämförelse för objekt-selectors — förhindrar omrendering vid oförändrad data
- Separera frekvent och sällan uppdaterat tillstånd — blanda dem inte i samma store-slice
Profilering och mätning
- Profilera med Hermes i release-byggen — development-byggen ger missvisande data
- Övervaka med Sentry Performance — identifiera flaskhalsar i produktionsmiljö
- Mät kallstarttid regelbundet — sikta på under 2 sekunder
- Övervaka minnesanvändning — fånga minnesläckor tidigt
- Testa på lågpresterande enheter — det är där optimeringens effekt syns tydligast
Nätverks- och dataprestanda
- Implementera paginering för stora datamängder — ladda inte allt på en gång
- Använd cache-strategier — React Query eller SWR för intelligent datahämtning
- Komprimera API-svar — aktivera gzip/brotli på servern
- Minimera bundle-storlek — analysera och eliminera onödiga beroenden
Sammanfattning
React Native 2026 levererar en prestandanivå som var otänkbar för bara några år sedan. Den nya arkitekturen med JSI, Fabric och TurboModules har eliminerat de grundläggande flaskhalsar som tidigare hindrade React Native från att riktigt konkurrera med nativa appar. React Compiler tar bort bördan av manuell memoization, och concurrent features som useTransition ger dig finkornig kontroll över renderingsprioriteringar.
Men tekniken ensam räcker inte. De mest performanta apparna byggs av team som mäter, analyserar och itererar kontinuerligt. Använd Hermes-profileringen, Sentry Performance och Chrome DevTools för att hitta de verkliga flaskhalsarna i din app. Fokusera på de optimeringar som ger störst effekt för just dina användare, och mät alltid resultatet.
Genom att följa rekommendationerna i den här guiden — från arkitekturbeslut ner till enskilda komponentoptimeringar — kan du bygga React Native-appar som levererar en användarupplevelse i absolut toppklass. Prestanda är inte längre en kompromiss i React Native. Det är en styrka.