décembre 21, 2025
18 min de lecture

Questions d'entretien pour développeur React Native senior : Guide complet

interview
career-advice
job-search
Questions d'entretien pour développeur React Native senior : Guide complet
MB

Milad Bonakdar

Auteur

Maîtrisez le développement React Native avancé avec des questions d'entretien essentielles couvrant l'optimisation des performances, les modules natifs, la gestion d'état, les tests, les modèles d'architecture et les meilleures pratiques multiplateformes pour les développeurs seniors.


Introduction

On attend des développeurs React Native seniors qu'ils conçoivent des applications multiplateformes évolutives, optimisent les performances, intègrent des modules natifs et prennent des décisions architecturales éclairées. Ce rôle exige une expertise approfondie dans React Native, la gestion d'état, le développement natif et la capacité à résoudre des défis complexes de développement mobile.

Ce guide complet couvre les questions d'entretien essentielles pour les développeurs React Native seniors, allant des concepts React avancés à l'optimisation des performances, en passant par la gestion d'état, les modules natifs, les tests et les modèles architecturaux. Chaque question comprend des réponses détaillées, une évaluation de la rareté et des niveaux de difficulté.


React et Hooks Avancés (5 Questions)

1. Expliquez useMemo et useCallback. Quand devriez-vous les utiliser ?

Réponse : Ces deux hooks optimisent les performances en mettant en cache les valeurs/fonctions.

  • useMemo : Met en cache les valeurs calculées (calculs coûteux)
  • useCallback : Met en cache les références de fonction (empêche la recréation)
  • Quand les utiliser : Uniquement lorsque vous rencontrez des problèmes de performance. Une optimisation prématurée peut rendre le code plus difficile à lire.
import { useMemo, useCallback, useState } from 'react';

function ExpensiveComponent({ items, onItemClick }) {
  // useMemo - mise en cache du calcul coûteux
  const sortedItems = useMemo(() => {
    console.log('Tri des éléments...');
    return items.sort((a, b) => a.price - b.price);
  }, [items]); // Recalculer uniquement lorsque les éléments changent
  
  // useCallback - mise en cache de la fonction
  const handleClick = useCallback((id) => {
    console.log('Élément cliqué :', id);
    onItemClick(id);
  }, [onItemClick]); // Recreer uniquement lorsque onItemClick change
  
  return (
    <FlatList
      data={sortedItems}
      renderItem={({ item }) => (
        <ItemRow item={item} onClick={handleClick} />
      )}
    />
  );
}

// Composant enfant avec React.memo
const ItemRow = React.memo(({ item, onClick }) => {
  console.log('Rendu de l'élément :', item.id);
  return (
    <TouchableOpacity onPress={() => onClick(item.id)}>
      <Text>{item.name}</Text>
    </TouchableOpacity>
  );
});

Rareté : Très Courant Difficulté : Moyenne


2. Qu'est-ce que useRef et quels sont ses cas d'utilisation ?

Réponse : useRef crée une référence mutable qui persiste entre les rendus sans provoquer de nouveaux rendus.

  • Cas d'utilisation :
    • Accéder aux éléments DOM/natifs
    • Stocker des valeurs mutables sans déclencher de nouveau rendu
    • Conserver les valeurs précédentes
    • Stocker les minuteurs/intervalles
import { useRef, useEffect } from 'react';
import { TextInput, Animated } from 'react-native';

function FormComponent() {
  const inputRef = useRef(null);
  const previousValue = useRef('');
  const animatedValue = useRef(new Animated.Value(0)).current;
  
  useEffect(() => {
    // Focus sur l'entrée au montage
    inputRef.current?.focus();
  }, []);
  
  const handleChange = (text) => {
    console.log('Précédent :', previousValue.current);
    console.log('Actuel :', text);
    previousValue.current = text;
  };
  
  const startAnimation = () => {
    Animated.timing(animatedValue, {
      toValue: 1,
      duration: 300,
      useNativeDriver: true,
    }).start();
  };
  
  return (
    <View>
      <TextInput ref={inputRef} onChangeText={handleChange} />
      <Animated.View style={{ opacity: animatedValue }}>
        <Text>Contenu animé</Text>
      </Animated.View>
    </View>
  );
}

// Exemple de minuteur
function Timer() {
  const intervalRef = useRef(null);
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    intervalRef.current = setInterval(() => {
      setCount(c => c + 1);
    }, 1000);
    
    return () => clearInterval(intervalRef.current);
  }, []);
  
  return <Text>{count}</Text>;
}

Rareté : Courant Difficulté : Moyenne


3. Expliquez les Hooks personnalisés et quand les créer.

Réponse : Les hooks personnalisés extraient la logique d'état réutilisable dans des fonctions séparées.

  • Avantages : Réutilisation du code, séparation des préoccupations, tests plus faciles
  • Convention : Doit commencer par "use"
// Hook personnalisé pour la récupération d'API
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const json = await response.json();
        setData(json);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    
    fetchData();
  }, [url]);
  
  return { data, loading, error };
}

// Hook personnalisé pour la gestion de formulaires
function useForm(initialValues) {
  const [values, setValues] = useState(initialValues);
  const [errors, setErrors] = useState({});
  
  const handleChange = (name, value) => {
    setValues(prev => ({ ...prev, [name]: value }));
  };
  
  const validate = (validationRules) => {
    const newErrors = {};
    Object.keys(validationRules).forEach(field => {
      const rule = validationRules[field];
      if (rule.required && !values[field]) {
        newErrors[field] = `${field} est requis`;
      }
    });
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };
  
  return { values, errors, handleChange, validate };
}

// Utilisation
function UserProfile() {
  const { data, loading, error } = useFetch('https://api.example.com/user');
  const { values, errors, handleChange, validate } = useForm({
    name: '',
    email: '',
  });
  
  if (loading) return <ActivityIndicator />;
  if (error) return <Text>Erreur : {error}</Text>;
  
  return <Text>{data.name}</Text>;
}

Rareté : Courant Difficulté : Moyenne


4. Qu'est-ce que le contexte React et quand devriez-vous l'utiliser ?

Réponse : Le contexte offre un moyen de transmettre des données à travers l'arbre des composants sans passer par le prop drilling.

  • Cas d'utilisation : Thème, authentification, préférences de langue
  • Attention : Peut provoquer des rendus inutiles s'il n'est pas utilisé avec précaution
import { createContext, useContext, useState } from 'react';

// Créer un contexte
const ThemeContext = createContext();
const AuthContext = createContext();

// Fournisseur de thème
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };
  
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Fournisseur d'authentification
function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  
  const login = async (credentials) => {
    const user = await loginAPI(credentials);
    setUser(user);
  };
  
  const logout = () => {
    setUser(null);
  };
  
  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

// Hooks personnalisés pour le contexte
function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme doit être utilisé dans ThemeProvider');
  }
  return context;
}

function useAuth() {
  return useContext(AuthContext);
}

// Utilisation
function App() {
  return (
    <ThemeProvider>
      <AuthProvider>
        <MainApp />
      </AuthProvider>
    </ThemeProvider>
  );
}

function ThemedButton() {
  const { theme, toggleTheme } = useTheme();
  const { user } = useAuth();
  
  return (
    <TouchableOpacity
      style={{ backgroundColor: theme === 'light' ? '#fff' : '#333' }}
      onPress={toggleTheme}
    >
      <Text>{user ? `Bonjour, ${user.name}` : 'Invité'}</Text>
    </TouchableOpacity>
  );
}

Rareté : Très Courant Difficulté : Moyenne


5. Expliquez la différence entre useEffect et useLayoutEffect.

Réponse : Les deux exécutent des effets secondaires, mais à des moments différents :

  • useEffect : S'exécute de manière asynchrone après que le rendu est affiché à l'écran
  • useLayoutEffect : S'exécute de manière synchrone avant l'affichage (bloque les mises à jour visuelles)
  • Utilisez useLayoutEffect lorsque : Vous devez mesurer le DOM ou éviter le scintillement visuel
import { useEffect, useLayoutEffect, useRef, useState } from 'react';

function MeasureComponent() {
  const [height, setHeight] = useState(0);
  const elementRef = useRef(null);
  
  // useLayoutEffect - mesurer avant l'affichage
  useLayoutEffect(() => {
    if (elementRef.current) {
      const { height } = elementRef.current.measure((x, y, width, height) => {
        setHeight(height);
      });
    }
  }, []);
  
  // useEffect - après l'affichage
  useEffect(() => {
    console.log('Composant rendu');
  }, []);
  
  return (
    <View ref={elementRef}>
      <Text>Hauteur : {height}</Text>
    </View>
  );
}

Rareté : Moyenne Difficulté : Difficile


Gestion d'État (4 Questions)

6. Expliquez Redux et ses principes fondamentaux.

Réponse : Redux est un conteneur d'état prévisible pour les applications JavaScript.

Loading diagram...
  • Principes fondamentaux :
    • Source unique de vérité (un seul store)
    • L'état est en lecture seule (envoyer des actions pour modifier)
    • Modifications effectuées avec des fonctions pures (reducers)
// Types d'action
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';

// Créateurs d'action
const addTodo = (text) => ({
  type: ADD_TODO,
  payload: { id: Date.now(), text, completed: false },
});

const toggleTodo = (id) => ({
  type: TOGGLE_TODO,
  payload: id,
});

// Reducer
const todosReducer = (state = [], action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.payload];
    case TOGGLE_TODO:
      return state.map(todo =>
        todo.id === action.payload
          ? { ...todo, completed: !todo.completed }
          : todo
      );
    default:
      return state;
  }
};

// Store
import { createStore } from 'redux';
const store = createStore(todosReducer);

// Composant React Native
import { useSelector, useDispatch } from 'react-redux';

function TodoList() {
  const todos = useSelector(state => state.todos);
  const dispatch = useDispatch();
  
  return (
    <View>
      <FlatList
        data={todos}
        renderItem={({ item }) => (
          <TouchableOpacity onPress={() => dispatch(toggleTodo(item.id))}>
            <Text style={{ textDecorationLine: item.completed ? 'line-through' : 'none' }}>
              {item.text}
            </Text>
          </TouchableOpacity>
        )}
      />
      <Button title="Ajouter" onPress={() => dispatch(addTodo('Nouvelle tâche'))} />
    </View>
  );
}

Rareté : Très Courant Difficulté : Difficile


7. Qu'est-ce que Redux Toolkit et comment simplifie-t-il Redux ?

Réponse : Redux Toolkit est la manière officielle recommandée d'écrire la logique Redux.

  • Avantages :
    • Moins de boilerplate
    • Immer intégré pour les mises à jour immuables
    • Inclut Redux Thunk
    • Meilleur support TypeScript
import { createSlice, configureStore } from '@reduxjs/toolkit';

// Slice (combine les actions et le reducer)
const todosSlice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    addTodo: (state, action) => {
      // Immer permet un code "mutant"
      state.push({
        id: Date.now(),
        text: action.payload,
        completed: false,
      });
    },
    toggleTodo: (state, action) => {
      const todo = state.find(t => t.id === action.payload);
      if (todo) {
        todo.completed = !todo.completed;
      }
    },
  },
});

export const { addTodo, toggleTodo } = todosSlice.actions;

// Store
const store = configureStore({
  reducer: {
    todos: todosSlice.reducer,
  },
});

// Thunk asynchrone
import { createAsyncThunk } from '@reduxjs/toolkit';

export const fetchTodos = createAsyncThunk(
  'todos/fetchTodos',
  async () => {
    const response = await fetch('https://api.example.com/todos');
    return response.json();
  }
);

const todosSlice = createSlice({
  name: 'todos',
  initialState: { items: [], loading: false, error: null },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchTodos.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchTodos.fulfilled, (state, action) => {
        state.loading = false;
        state.items = action.payload;
      })
      .addCase(fetchTodos.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  },
});

Rareté : Courant Difficulté : Moyenne


8. Quelles sont les alternatives à Redux pour la gestion d'état ?

Réponse : Plusieurs solutions de gestion d'état existent :

  • Context API + useReducer : Intégré, bon pour les applications simples
  • MobX : Basé sur les observables, moins de boilerplate
  • Zustand : Minimal, basé sur les hooks
  • Recoil : Basé sur les atomes, par Facebook
  • Jotai : Atomes primitifs
// Exemple Zustand
import create from 'zustand';

const useStore = create((set) => ({
  todos: [],
  addTodo: (text) => set((state) => ({
    todos: [...state.todos, { id: Date.now(), text, completed: false }],
  })),
  toggleTodo: (id) => set((state) => ({
    todos: state.todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ),
  })),
}));

// Utilisation
function TodoList() {
  const { todos, addTodo, toggleTodo } = useStore();
  
  return (
    <View>
      <FlatList
        data={todos}
        renderItem={({ item }) => (
          <TouchableOpacity onPress={() => toggleTodo(item.id)}>
            <Text>{item.text}</Text>
          </TouchableOpacity>
        )}
      />
    </View>
  );
}

Rareté : Courant Difficulté : Moyenne


9. Comment gérez-vous les effets secondaires dans Redux ?

Réponse : Utilisez un middleware pour les opérations asynchrones :

  • Redux Thunk : Fonctions qui renvoient des fonctions
  • Redux Saga : Basé sur les générateurs, plus puissant
  • Redux Observable : Basé sur RxJS
// Redux Thunk
const fetchUser = (userId) => async (dispatch) => {
  dispatch({ type: 'FETCH_USER_REQUEST' });
  
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`);
    const user = await response.json();
    dispatch({ type: 'FETCH_USER_SUCCESS', payload: user });
  } catch (error) {
    dispatch({ type: 'FETCH_USER_FAILURE', payload: error.message });
  }
};

// Utilisation
dispatch(fetchUser(123));

// Redux Saga
import { call, put, takeEvery } from 'redux-saga/effects';

function* fetchUserSaga(action) {
  try {
    const user = yield call(fetch, `https://api.example.com/users/${action.payload}`);
    const data = yield call([user, 'json']);
    yield put({ type: 'FETCH_USER_SUCCESS', payload: data });
  } catch (error) {
    yield put({ type: 'FETCH_USER_FAILURE', payload: error.message });
  }
}

function* watchFetchUser() {
  yield takeEvery('FETCH_USER_REQUEST', fetchUserSaga);
}

Rareté : Courant Difficulté : Difficile


Optimisation des Performances (5 Questions)

10. Comment optimisez-vous les performances de FlatList ?

Réponse : Plusieurs stratégies améliorent le défilement de FlatList :

  1. Utilisez keyExtractor : Fournissez des clés uniques
  2. getItemLayout : Évitez la mesure pour les éléments de hauteur fixe
  3. removeClippedSubviews : Démontez les vues hors écran (Android)
  4. maxToRenderPerBatch : Contrôlez la taille du lot
  5. windowSize : Contrôlez la fenêtre rendue
  6. initialNumToRender : Éléments à rendre initialement
  7. Mémorisez renderItem : Empêchez les rendus inutiles
import React, { memo, useCallback } from 'react';

const ITEM_HEIGHT = 80;

// Composant d'élément mémorisé
const ListItem = memo(({ item, onPress }) => {
  return (
    <TouchableOpacity onPress={() => onPress(item.id)} style={{ height: ITEM_HEIGHT }}>
      <Text>{item.name}</Text>
    </TouchableOpacity>
  );
});

function OptimizedList({ data }) {
  const handlePress = useCallback((id) => {
    console.log('Appuyé :', id);
  }, []);
  
  const renderItem = useCallback(({ item }) => (
    <ListItem item={item} onPress={handlePress} />
  ), [handlePress]);
  
  const keyExtractor = useCallback((item) => item.id.toString(), []);
  
  const getItemLayout = useCallback((data, index) => ({
    length: ITEM_HEIGHT,
    offset: ITEM_HEIGHT * index,
    index,
  }), []);
  
  return (
    <FlatList
      data={data}
      renderItem={renderItem}
      keyExtractor={keyExtractor}
      getItemLayout={getItemLayout}
      removeClippedSubviews={true}
      maxToRenderPerBatch={10}
      updateCellsBatchingPeriod={50}
      initialNumToRender={10}
      windowSize={5}
    />
  );
}

Rareté : Très Courant Difficulté : Moyenne


11. Qu'est-ce que le pont React Native et comment affecte-t-il les performances ?

Réponse : Le pont est la couche de communication entre JavaScript et le code natif.

  • Comment ça marche :
    • JavaScript s'exécute dans un thread séparé
    • Les modules natifs s'exécutent dans des threads natifs
    • Le pont sérialise les données entre eux (JSON)
  • Impact sur les performances :
    • La communication par pont est asynchrone
    • Surcharge de sérialisation
    • Peut devenir un goulot d'étranglement avec une communication fréquente
  • Solutions :
    • Minimiser les traversées de pont
    • Opérations par lots
    • Utilisez des animations natives (contourner le pont)
    • Nouvelle architecture (JSI) supprime le pont
// Mauvais - traversées de pont fréquentes
const BadAnimation = () => {
  const [position, setPosition] = useState(0);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setPosition(p => p + 1); // Traversée de pont à chaque frame !
    }, 16);
    return () => clearInterval(interval);
  }, []);
  
  return <View style={{ transform: [{ translateX: position }] }} />;
};

// Bon - animation native (pas de pont)
const GoodAnimation = () => {
  const translateX = useRef(new Animated.Value(0)).current;
  
  useEffect(() => {
    Animated.timing(translateX, {
      toValue: 100,
      duration: 1000,
      useNativeDriver: true, // S'exécute sur le thread natif !
    }).start();
  }, []);
  
  return <Animated.View style={{ transform: [{ translateX }] }} />;
};

Rareté : Courant Difficulté : Difficile


12. Comment évitez-vous les rendus inutiles ?

Réponse : Plusieurs techniques empêchent les rendus gaspillés :

  1. React.memo : Mémorisez les composants
  2. useMemo/useCallback : Mémorisez les valeurs/fonctions
  3. Props de clé appropriées : Aidez React à identifier les modifications
  4. Évitez les objets/tableaux en ligne : Créez de nouvelles références
  5. Divisez les composants : Composants plus petits et ciblés
// Mauvais - crée un nouvel objet à chaque rendu
function BadComponent() {
  return <ChildComponent style={{ margin: 10 }} />; // Nouvel objet !
}

// Bon - référence stable
const styles = StyleSheet.create({
  container: { margin: 10 },
});

function GoodComponent() {
  return <ChildComponent style={styles.container} />;
}

// React.memo avec comparaison personnalisée
const ExpensiveComponent = React.memo(
  ({ data, onPress }) => {
    console.log('Rendu de ExpensiveComponent');
    return (
      <View>
        <Text>{data.name}</Text>
        <Button onPress={onPress} />
      </View>
    );
  },
  (prevProps, nextProps) => {
    // Comparaison personnalisée - ne rendre que si data.id a changé
    return prevProps.data.id === nextProps.data.id;
  }
);

// Divisez les composants pour isoler les rendus
function ParentComponent() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');
  
  return (
    <View>
      {/* Ne se rend que lorsque le nombre change */}
      <CountDisplay count={count} />
      
      {/* Ne se rend que lorsque le texte change */}
      <TextDisplay text={text} />
      
      <Button onPress={() => setCount(c => c + 1)} />
    </View>
  );
}

const CountDisplay = React.memo(({ count }) => <Text>{count}</Text>);
const TextDisplay = React.memo(({ text }) => <Text>{text}</Text>);

Rareté : Très Courant Difficulté : Moyenne


13. Comment optimisez-vous les images dans React Native ?

Réponse : L'optimisation des images est cruciale pour les performances :

  1. Redimensionnez les images : Utilisez les dimensions appropriées
  2. Mettez les images en cache : Utilisez des bibliothèques comme react-native-fast-image
  3. Chargement paresseux : Chargez les images à la demande
  4. Chargement progressif : Affichez d'abord un espace réservé
  5. Utilisez le format WebP : Meilleure compression
import FastImage from 'react-native-fast-image';

function OptimizedImage({ uri }) {
  return (
    <FastImage
      source={{
        uri,
        priority: FastImage.priority.normal,
        cache: FastImage.cacheControl.immutable,
      }}
      resizeMode={FastImage.resizeMode.cover}
      style={{ width: 200, height: 200 }}
    />
  );
}

// Chargement progressif des images
function ProgressiveImage({ thumbnailUri, fullUri }) {
  const [imageLoaded, setImageLoaded] = useState(false);
  
  return (
    <View>
      <Image
        source={{ uri: thumbnailUri }}
        style={styles.image}
        blurRadius={imageLoaded ? 0 : 5}
      />
      <Image
        source={{ uri: fullUri }}
        style={[styles.image, { opacity: imageLoaded ? 1 : 0 }]}
        onLoad={() => setImageLoaded(true)}
      />
    </View>
  );
}

// Préchargement des images
import { Image } from 'react-native';

const prefetchImages = async (urls) => {
  const promises = urls.map(url => Image.prefetch(url));
  await Promise.all(promises);
};

Rareté : Courant Difficulté : Moyenne


14. Quels outils utilisez-vous pour le profilage des performances ?

Réponse : Plusieurs outils aident à identifier les problèmes de performances :

  • React DevTools Profiler : Temps de rendu des composants
  • Flipper : Outil de débogage et de profilage
  • Performance Monitor : Moniteur FPS intégré
  • Systrace : Traçage des performances Android
  • Instruments : Profilage des performances iOS
// Activer le moniteur de performances en développement
import { LogBox } from 'react-native';

if (__DEV__) {
  // Afficher le moniteur de performances
  require('react-native').unstable_enableLogBox();
}

// Mesurer le temps de rendu des composants
import { Profiler } from 'react';

function onRenderCallback(
  id,
  phase,
  actualDuration,
  baseDuration,
  startTime,
  commitTime
) {
  console.log(`${id} (${phase}) a pris ${actualDuration}ms`);
}

function App() {
  return (
    <Profiler id="App" onRender={onRenderCallback}>
      <MyComponent />
    </Profiler>
  );
}

// Suivi personnalisé des performances
const measurePerformance = (name, fn) => {
  const start = performance.now();
  const result = fn();
  const end = performance.now();
  console.log(`${name} a pris ${end - start}ms`);
  return result;
};

Rareté : Courant Difficulté : Moyenne


Modules Natifs et Spécificités de la Plateforme (4 Questions)

15. Comment créez-vous un module natif dans React Native ?

Réponse : Les modules natifs vous permettent d'utiliser du code spécifique à la plateforme.

// iOS (Objective-C) - CalendarManager.m
#import "CalendarManager.h"
#import <React/RCTLog.h>

@implementation CalendarManager

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location)
{
  RCTLogInfo(@"Creating event %@ at %@", name, location);
}

@end

// Android (Java) - CalendarModule.java
package com.myapp;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class CalendarModule extends ReactContextBaseJavaModule {
  CalendarModule(ReactApplicationContext context) {
    super(context);
  }

  @Override
  public String getName() {
    return "CalendarManager";
  }

  @ReactMethod
  public void addEvent(String name, String location) {
    Log.d("CalendarModule", "Creating event " + name + " at " + location);
  }
}

// Utilisation JavaScript
import { NativeModules } from 'react-native';

const { CalendarManager } = NativeModules;

function MyComponent() {
  const createEvent = () => {
    CalendarManager.addEvent('Meeting', 'Office');
  };
  
  return <Button title="Créer un événement" onPress={createEvent} />;
}

Rareté : Moyenne Difficulté : Difficile


16. Comment gérez-vous le code spécifique à la plateforme ?

Réponse : Plusieurs approches pour le code spécifique à la plateforme :

  1. Module Platform : Vérifiez la plateforme au moment de l'exécution
  2. Fichiers spécifiques à la plateforme : .ios.js et .android.js
  3. Platform.select : Sélectionnez les valeurs en fonction de la plateforme
import { Platform } from 'react-native';

// Module Platform
const styles = StyleSheet.create({
  container: {
    paddingTop: Platform.OS === 'ios' ? 20 : 0,
  },
});

// Platform.select
const styles = StyleSheet.create({
  container: {
    ...Platform.select({
      ios: {
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.3,
      },
      android: {
        elevation: 4,
      },
    }),
  },
});

// Fichiers spécifiques à la plateforme
// Button.ios.js
export default function Button() {
  return <Text>Bouton iOS</Text>;
}

// Button.android.js
export default function Button() {
  return <Text>Bouton Android</Text>;
}

// Utilisation - sélectionne automatiquement le bon fichier
import Button from './Button';

// Vérification de la version de la plateforme
if (Platform.Version >= 21) {
  // Android API 21+
}

Rareté : Très Courant Difficulté : Facile


17. Qu'est-ce que la nouvelle architecture (Fabric et TurboModules) ?

Réponse : La nouvelle architecture améliore les performances de React Native :

  • Fabric : Nouveau système de rendu
    • Disposition synchrone
    • Meilleure interopérabilité avec les vues natives
    • Sécurité de type
  • TurboModules : Nouveau système de modules natifs
    • Chargement paresseux
    • JSI (JavaScript Interface) - communication C++ directe
    • Pas de sérialisation de pont

Avantages :

  • Démarrage plus rapide
  • Utilisation de la mémoire réduite
  • Appels natifs synchrones
  • Meilleure sécurité de type

Rareté : Moyenne Difficulté : Difficile


18. Comment gérez-vous les liens profonds dans React Native ?

Réponse : Les liens profonds permettent d'ouvrir des écrans spécifiques à partir d'URL.

import { Linking } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';

// Configurer les liens profonds
const linking = {
  prefixes: ['myapp://', 'https://myapp.com'],
  config: {
    screens: {
      Home: 'home',
      Profile: 'profile/:id',
      Settings: 'settings',
    },
  },
};

function App() {
  return (
    <NavigationContainer linking={linking}>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Profile" component={ProfileScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

// Gérer les liens entrants
useEffect(() => {
  const handleUrl = ({ url }) => {
    console.log('Ouvert avec l\'URL :', url);
    // myapp://profile/123
  };
  
  // Application ouverte à partir d'un lien
  Linking.getInitialURL().then(url => {
    if (url) handleUrl({ url });
  });
  
  // Application déjà ouverte, nouveau lien
  const subscription = Linking.addEventListener('url', handleUrl);
  
  return () => subscription.remove();
}, []);
Newsletter subscription

Conseils de carrière hebdomadaires qui fonctionnent vraiment

Recevez les dernières idées directement dans votre boîte de réception

Decorative doodle

Démarquez-vous auprès des Recruteurs et Décrochez Votre Emploi de Rêve

Rejoignez des milliers de personnes qui ont transformé leur carrière avec des CV alimentés par l'IA qui passent les ATS et impressionnent les responsables du recrutement.

Commencer maintenant

Partager cet article

Soyez Embauché 50% Plus Rapidement

Les chercheurs d'emploi utilisant des CV professionnels améliorés par l'IA décrochent des postes en moyenne en 5 semaines contre 10 normalement. Arrêtez d'attendre et commencez à passer des entretiens.