Développement d'Applications React Native en 2026 : Guide Complet et Questions d'Entretien
Maîtrisez le développement d'applications React Native en 2026 avec la Nouvelle Architecture, Hermes V1 et Fabric. Exemples de code pratiques et questions d'entretien techniques.

Le développement d'applications React Native en 2026 a fondamentalement évolué avec la version 0.87 qui intègre désormais la Nouvelle Architecture comme seule option disponible. L'ancien bridge qui sérialisait chaque appel JavaScript-vers-native en JSON a disparu, remplacé par JSI (JavaScript Interface) pour une communication synchrone directe.
React Native 0.87 rend la Nouvelle Architecture obligatoire. L'ancien bridge est complètement supprimé. Le rendu des listes complexes est 43% plus rapide, les pertes de frames lors du défilement ont diminué de 95%, et l'utilisation mémoire a baissé de 33% dans les tests de benchmark.
Comprendre JSI et la Nouvelle Architecture
JSI (JavaScript Interface) remplace le bridge asynchrone par des bindings C++ directs entre JavaScript et le code natif. Au lieu de sérialiser les données en JSON, de les passer par une file de messages, et de les désérialiser de l'autre côté, JSI permet à JavaScript de détenir des références vers des objets natifs et d'appeler leurs méthodes directement.
Ce changement architectural permet trois capacités essentielles : les appels natifs synchrones, la propriété partagée des objets entre les couches JavaScript et native, et le chargement différé des modules natifs.
import { TurboModuleRegistry, TurboModule } from 'react-native';
export interface Spec extends TurboModule {
getUserProfile(userId: string): Promise<{
id: string;
name: string;
email: string;
}>;
// Synchronous call - only possible with JSI
getDeviceLocale(): string;
}
export default TurboModuleRegistry.getEnforcing<Spec>('UserModule');La méthode getDeviceLocale() retourne immédiatement sans attendre de Promise. Cela était impossible avec l'ancien bridge où chaque appel natif nécessitait une sérialisation asynchrone.
Construire un Composant Production avec Fabric
Fabric est le nouveau système de rendu qui fonctionne aux côtés de JSI. Il gère l'arbre UI en C++ et se synchronise directement avec le thread JavaScript, éliminant les "saccades UI" qui se produisaient quand l'ancien bridge prenait du retard lors de mises à jour rapides.
import React, { memo, useCallback } from 'react';
import {
View,
Text,
Image,
Pressable,
StyleSheet,
} from 'react-native';
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
interface Product {
id: string;
name: string;
price: number;
imageUrl: string;
inStock: boolean;
}
interface ProductCardProps {
product: Product;
onPress: (id: string) => void;
}
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
export const ProductCard = memo(function ProductCard({
product,
onPress,
}: ProductCardProps) {
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
const handlePressIn = useCallback(() => {
scale.value = withSpring(0.95);
}, [scale]);
const handlePressOut = useCallback(() => {
scale.value = withSpring(1);
}, [scale]);
const handlePress = useCallback(() => {
onPress(product.id);
}, [onPress, product.id]);
return (
<AnimatedPressable
style={[styles.card, animatedStyle]}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onPress={handlePress}
accessibilityRole="button"
accessibilityLabel={`${product.name}, ${product.price} dollars`}
>
<Image
source={{ uri: product.imageUrl }}
style={styles.image}
resizeMode="cover"
/>
<View style={styles.content}>
<Text style={styles.name} numberOfLines={2}>
{product.name}
</Text>
<Text style={styles.price}>${product.price.toFixed(2)}</Text>
{!product.inStock && (
<Text style={styles.outOfStock}>Out of Stock</Text>
)}
</View>
</AnimatedPressable>
);
});
const styles = StyleSheet.create({
card: {
backgroundColor: '#ffffff',
borderRadius: 12,
overflow: 'hidden',
marginHorizontal: 8,
marginVertical: 4,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
image: {
width: '100%',
height: 160,
},
content: {
padding: 12,
},
name: {
fontSize: 16,
fontWeight: '600',
color: '#1a1a1a',
marginBottom: 4,
},
price: {
fontSize: 18,
fontWeight: '700',
color: '#2563eb',
},
outOfStock: {
fontSize: 12,
color: '#dc2626',
marginTop: 4,
},
});Ce composant utilise react-native-reanimated qui exécute les animations sur le thread UI via JSI. Les hooks useSharedValue et useAnimatedStyle communiquent directement avec le code natif sans passer par le bridge.
Gestion d'État avec TanStack Query
L'état serveur dans les applications React Native bénéficie d'outils dédiés. TanStack Query gère la mise en cache, le rafraîchissement en arrière-plan et les mises à jour optimistes sans nécessiter de conteneur d'état global.
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
interface Product {
id: string;
name: string;
price: number;
imageUrl: string;
inStock: boolean;
}
const API_BASE = 'https://api.example.com';
async function fetchProducts(category?: string): Promise<Product[]> {
const url = category
? `${API_BASE}/products?category=${category}`
: `${API_BASE}/products`;
const response = await fetch(url);
if (!response.ok) {
throw new Error('Failed to fetch products');
}
return response.json();
}
export function useProducts(category?: string) {
return useQuery({
queryKey: ['products', category],
queryFn: () => fetchProducts(category),
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 30 * 60 * 1000, // 30 minutes
});
}
export function useToggleStock() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (productId: string) => {
const response = await fetch(`${API_BASE}/products/${productId}/toggle-stock`, {
method: 'POST',
});
if (!response.ok) {
throw new Error('Failed to update stock');
}
return response.json();
},
// Optimistic update
onMutate: async (productId) => {
await queryClient.cancelQueries({ queryKey: ['products'] });
const previousProducts = queryClient.getQueryData<Product[]>(['products']);
queryClient.setQueryData<Product[]>(['products'], (old) =>
old?.map((p) =>
p.id === productId ? { ...p, inStock: !p.inStock } : p
)
);
return { previousProducts };
},
onError: (_err, _productId, context) => {
if (context?.previousProducts) {
queryClient.setQueryData(['products'], context.previousProducts);
}
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['products'] });
},
});
}Le callback onMutate effectue une mise à jour optimiste avant que le serveur ne réponde. Si la mutation échoue, onError restaure l'état précédent. Ce pattern offre un retour visuel instantané tout en maintenant la cohérence des données.
Prêt à réussir tes entretiens React Native ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Navigation avec Expo Router
Expo Router fournit un routage basé sur les fichiers pour React Native, similaire à Next.js App Router. La structure des fichiers définit automatiquement les routes.
import { Tabs } from 'expo-router';
import { Home, Search, ShoppingCart, User } from 'lucide-react-native';
export default function TabsLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: '#2563eb',
tabBarInactiveTintColor: '#6b7280',
headerShown: false,
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Home',
tabBarIcon: ({ color, size }) => (
<Home color={color} size={size} />
),
}}
/>
<Tabs.Screen
name="search"
options={{
title: 'Search',
tabBarIcon: ({ color, size }) => (
<Search color={color} size={size} />
),
}}
/>
<Tabs.Screen
name="cart"
options={{
title: 'Cart',
tabBarIcon: ({ color, size }) => (
<ShoppingCart color={color} size={size} />
),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: 'Profile',
tabBarIcon: ({ color, size }) => (
<User color={color} size={size} />
),
}}
/>
</Tabs>
);
}Les routes dynamiques utilisent la notation entre crochets. Un fichier à app/product/[id].tsx gère tout chemin /product/123 :
import { useLocalSearchParams } from 'expo-router';
import { View, Text, ActivityIndicator } from 'react-native';
import { useQuery } from '@tanstack/react-query';
export default function ProductDetailScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
const { data: product, isLoading, error } = useQuery({
queryKey: ['product', id],
queryFn: () => fetchProduct(id),
enabled: !!id,
});
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#2563eb" />
</View>
);
}
if (error || !product) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Product not found</Text>
</View>
);
}
return (
<View style={{ flex: 1, padding: 16 }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>{product.name}</Text>
<Text style={{ fontSize: 20, color: '#2563eb' }}>
${product.price.toFixed(2)}
</Text>
</View>
);
}Questions d'Entretien Courantes sur l'Architecture React Native
Les entretiens techniques pour les postes React Native en 2026 se concentrent fortement sur la Nouvelle Architecture. Les questions suivantes apparaissent fréquemment.
Les recruteurs s'attendent à ce que les candidats expliquent JSI, Fabric et TurboModules à un niveau conceptuel. Mémoriser la syntaxe importe moins que comprendre pourquoi l'architecture a changé et quels problèmes elle résout.
Question : Qu'est-ce que JSI et pourquoi React Native l'a-t-il adopté ?
JSI (JavaScript Interface) est une couche C++ qui permet à JavaScript de détenir des références vers des objets natifs et d'appeler leurs méthodes directement. L'ancien bridge sérialisait chaque appel en JSON, le plaçait dans une file asynchrone, et le désérialisait côté natif. Cela ajoutait de la latence et empêchait les opérations synchrones.
Avec JSI, une fonction JavaScript peut appeler une méthode native et recevoir le résultat dans la même frame. Cela permet des fonctionnalités comme les mesures de layout synchrones et la manipulation directe des vues natives.
Question : En quoi Fabric diffère-t-il de l'ancien renderer ?
Fabric est un système de rendu C++ qui maintient l'arbre UI dans le code natif plutôt que dans JavaScript. L'ancien renderer conservait le shadow tree en JavaScript et envoyait des lots de mises à jour à travers le bridge.
Avantages de Fabric :
- Calculs de layout synchrones via JSI
- Support du rendu concurrent (les fonctionnalités React 18 fonctionnent correctement)
- Meilleure gestion mémoire avec propriété partagée entre JS et natif
- Réduction de l'overhead de sérialisation
Question : Que sont les TurboModules ?
Les TurboModules remplacent les Native Modules. Les différences clés :
- Chargement différé : Les TurboModules ne se chargent que lors du premier accès, réduisant le temps de démarrage
- Typage sûr : CodeGen génère des bindings typés à partir des spécifications TypeScript
- Méthodes synchrones : Les TurboModules peuvent exposer des fonctions synchrones si nécessaire
- Accès JSI direct : Pas de sérialisation bridge
Question : Quand utiliser une méthode native synchrone ?
Les méthodes natives synchrones conviennent aux opérations qui :
- Se terminent en microsecondes (lecture de la locale appareil, vérification du statut des permissions)
- Bloquent l'UI intentionnellement (confirmation modale avant navigation)
- Retournent des valeurs nécessaires pour le rendu immédiat
Éviter les méthodes synchrones pour :
- Les requêtes réseau
- Les E/S fichiers au-delà de petites lectures
- Les requêtes base de données
- Toute opération dépassant 16ms (bloque la frame)
Pour plus de questions d'entretien React Native, consultez le module réseau et API et la section modules natifs.
Tester les Composants React Native
React Native Testing Library fournit des utilitaires pour tester les composants comme les utilisateurs interagissent avec eux, en se concentrant sur l'accessibilité et le comportement plutôt que sur les détails d'implémentation.
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react-native';
import { ProductCard } from '../components/ProductCard';
const mockProduct = {
id: 'prod-1',
name: 'Wireless Headphones',
price: 149.99,
imageUrl: 'https://example.com/headphones.jpg',
inStock: true,
};
describe('ProductCard', () => {
it('displays product information', () => {
const onPress = jest.fn();
render(<ProductCard product={mockProduct} onPress={onPress} />);
expect(screen.getByText('Wireless Headphones')).toBeOnTheScreen();
expect(screen.getByText('$149.99')).toBeOnTheScreen();
});
it('calls onPress with product id when pressed', () => {
const onPress = jest.fn();
render(<ProductCard product={mockProduct} onPress={onPress} />);
fireEvent.press(
screen.getByRole('button', { name: /wireless headphones/i })
);
expect(onPress).toHaveBeenCalledWith('prod-1');
expect(onPress).toHaveBeenCalledTimes(1);
});
it('shows out of stock message when product unavailable', () => {
const outOfStockProduct = { ...mockProduct, inStock: false };
render(<ProductCard product={outOfStockProduct} onPress={jest.fn()} />);
expect(screen.getByText('Out of Stock')).toBeOnTheScreen();
});
});Les tests interrogent par contenu textuel et rôles d'accessibilité plutôt que par test IDs ou internes du composant. Cette approche détecte les régressions affectant les utilisateurs tout en restant résistante au refactoring.
Monitoring de Performance en Production
React Native 0.87 s'intègre avec Sentry et des outils similaires pour le monitoring de performance en production. Métriques clés à suivre :
- Time to Interactive (TTI) : Temps avant que l'app réponde aux interactions utilisateur
- Pertes de frames : Frames qui prennent plus de 16,67ms à rendre
- Utilisation du thread JavaScript : Une utilisation élevée indique des calculs coûteux bloquant l'UI
- Croissance mémoire : Des augmentations constantes suggèrent des fuites
import * as Sentry from '@sentry/react-native';
import { useEffect } from 'react';
import { AppState, AppStateStatus } from 'react-native';
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
tracesSampleRate: 0.2,
profilesSampleRate: 0.1,
enableAutoPerformanceTracing: true,
});
export default function RootLayout() {
useEffect(() => {
const subscription = AppState.addEventListener(
'change',
(state: AppStateStatus) => {
if (state === 'active') {
Sentry.addBreadcrumb({
category: 'app.lifecycle',
message: 'App became active',
level: 'info',
});
}
}
);
return () => subscription.remove();
}, []);
// ... rest of layout
}Points Clés pour le Développement React Native en 2026
- La Nouvelle Architecture (JSI, Fabric, TurboModules) est obligatoire dans React Native 0.87. L'ancien bridge n'existe plus.
- JSI permet les appels natifs synchrones. Les utiliser avec parcimonie pour les opérations sous 16ms.
- Fabric rend l'UI en C++ et se synchronise avec JavaScript via JSI. Cela élimine le goulot d'étranglement du rendu asynchrone.
- Les TurboModules se chargent paresseusement et fournissent des bindings typés générés à partir des specs TypeScript.
- Expo Router offre une navigation basée sur les fichiers similaire à Next.js App Router.
- React Native Testing Library teste les composants à travers leur API publique et l'arbre d'accessibilité.
- Les applications en production doivent suivre le TTI, les pertes de frames et l'utilisation mémoire dès le premier jour.
Pour un aperçu plus approfondi de la construction d'applications complètes, consultez le tutoriel application complète React Native. Le guide Nouvelle Architecture couvre la migration depuis les anciennes versions.
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Tu saurais repérer le bug en React Native ?
Un vrai bout de code, un bug caché, une tentative par jour. Sans compte pour essayer.

Écrit par
Anthony Fillion-MailletFondateur de SharpSkill
Développeur fullstack depuis plus de 10 ans. Il dirige SharpSkill et répond de tout ce qui y est publié.
Mis à jour le 6 septembre 2026
Tags
Partager
Articles similaires

React Native et TypeScript en 2026 : Architecture Type-Safe et Questions d'Entretien
Développer des applications React Native type-safe avec TypeScript, Codegen, TurboModules et l'API Strict TypeScript. Architecture, navigation typée, exigences de la chaîne d'outils pour 0.87 et questions d'entretien.

React Native 0.87 et SwiftPM en 2026 : Build iOS Moderne et Questions d'Entretien
React Native 0.87 introduit le support expérimental de Swift Package Manager, éliminant CocoaPods des builds iOS. Ce guide couvre la configuration SwiftPM, l'API TypeScript Stricte, les optimisations Metro 0.87, et les questions d'entretien pour développeurs mobile seniors.

Nouvelle Architecture React Native en 2026 : Hermes V1, Mode Bridgeless et Questions d'Entretien
La Nouvelle Architecture React Native est désormais le standard en 2026 avec Hermes V1, le mode Bridgeless, les TurboModules et Fabric. Analyse approfondie des gains de performance, des patterns de migration et des questions d'entretien incontournables.