React
Senior
Quiz-React-Senior
Memoization
Usememo
Usecallback
Code-Splitting
Lazy-Loading
React-Testing-Library
Patterns-React
Architecture-React
Questions-Entretien-React-Senior
Qcm-React-Avance
Front-End
📝
Entretien React Senior : performance et testing
20 questions React avancées : memoization, useMemo, useCallback, code splitting, lazy loading, testing avec RTL, patterns avancés et architecture pour React Senior.
Banque de révision : les 20 questions corrigées
Voici l'intégralité des 20 questions de « Entretien React Senior : performance et testing », chacune avec sa bonne réponse et son explication. Le quiz interactif ci-dessus en tire une sélection aléatoire à chaque tentative — utilisez cette liste complète pour réviser.
Explication :
Le rendu concurrent permet à React de préparer plusieurs versions de l'UI en mémoire, d'interrompre un rendu long pour gérer une interaction utilisateur urgente, et de reprendre le rendu interrompu. Les fonctionnalités comme
Suspense, useTransition et useDeferredValue exploitent ce mécanisme.
Le mode concurrent est activé automatiquement avec
createRoot() dans React 18+. render() reste en mode legacy.
Explication :
Les RSC permettent d'exécuter des composants exclusivement côté serveur. Ces composants peuvent accéder directement aux bases de données, au système de fichiers, sans exposer de code au client, et ne sont pas inclus dans le bundle JavaScript.
Distinction clé : RSC ≠ SSR. Le SSR génère du HTML initial ; les RSC peuvent être exécutés à la demande pour charger des données sans envoyer de JS client.
Explication :
useTransition retourne [isPending, startTransition]. Les mises à jour dans startTransition sont marquées comme non urgentes : React peut les interrompre pour gérer des interactions utilisateur plus prioritaires (ex: taper dans un input).
Utilisez startTransition autour des mises à jour coûteuses (filtrage d'une longue liste) pendant que l'utilisateur tape, pour que l'input reste fluide.
Explication :
useDeferredValue(valeur) retourne une version "déférée" de la valeur qui ne se mettra à jour qu'une fois les rendus urgents terminés. Contrairement à useTransition, il ne nécessite pas de contrôler le setState (utile quand la valeur vient d'une source externe).
À utiliser quand vous recevez des données d'une bibliothèque tierce et que vous voulez éviter que ses mises à jour ne bloquent votre UI.
Explication :
La réconciliation est l'algorithme de diffing de React : il compare deux arbres Virtual DOM, identifie les différences (type, props, children), et génère un patch minimal à appliquer au DOM réel. L'algorithme O(n) repose sur deux hypothèses : éléments de type différent produisent des arbres différents, et les clés (keys) stabilisent l'identité.
Comprendre la réconciliation aide à optimiser : une clé stable empêche la recréation inutile, et changer le type d'un élément force le démontage/remontage complet.
Explication :
Avant React 18, le batching ne fonctionnait que dans les gestionnaires d'événements React. Avec le batching automatique, les mises à jour dans les promesses, setTimeout, et événements natifs sont aussi groupées, réduisant le nombre de re-rendus.
Pour échapper au batching (cas rare), utilisez
flushSync(). Cela force une mise à jour synchrone immédiate du DOM.
Explication :
Le pattern Compound Components permet de créer un ensemble de composants qui partagent un état interne et fonctionnent ensemble. Exemple :
<Select> contient <Select.Option>. L'état est partagé via Context. Cela offre une API déclarative et flexible.
Les bibliothèques UI comme Mantine, Radix UI, et Headless UI utilisent massivement ce pattern. Il évite d'avoir à passer toutes les props à travers un seul composant monolithique.
Explication :
TypeScript s'intègre avec React via des types utilitaires :
React.FC<Props>, React.ReactNode pour les children, React.ComponentProps<typeof Composant> pour extraire les props, React.CSSProperties pour les styles, etc.
Évitez
React.FC qui ajoute implicitement children. Préférez typer les props directement : function Comp({ name }: { name: string }).
Explication :
Le pattern State Reducer donne le contrôle total du reducer interne d'un composant à son utilisateur via une prop. L'utilisateur peut intercepter et modifier les actions. C'est une inversion de contrôle puissante, utilisée dans Downshift.
Ce pattern est avancé : combinez-le avec un reducer par défaut et utilisez la composition de reducers pour ne pas rompre le comportement par défaut.
Explication :
Dans l'App Router Next.js, les composants sont "serveur" par défaut (pas d'état, pas d'événements). Pour ajouter de l'interactivité, on isole cette partie dans un composant "client" marqué avec
"use client" en haut du fichier.
Bonne pratique : gardez la structure et le chargement de données côté serveur, et islez l'interactivité dans des composants client feuilles.
Explication :
Flux (Facebook) propose un flux unidirectionnel avec plusieurs stores. Redux s'inspire de Flux mais simplifie : un seul store, un reducer racine (fonction pure), et pas de dispatcher multiple. Redux Toolkit modernise encore avec des slices et Immer pour l'immutabilité.
Redux suit trois principes : source unique de vérité, état en lecture seule, modifications via des fonctions pures (reducers).
Explication :
Pour éviter totalement un re-rendu, il faut garantir l'égalité référentielle de toutes les props :
React.memo pour le composant enfant, useCallback pour les fonctions, useMemo pour les objets/tableaux. Si toutes les références sont stables, React.memo bloquera le re-rendu.
Dans la pratique, le profilage (React DevTools Profiler) doit guider l'optimisation. Ne pas optimiser prématurément.
Explication :
Le pattern Provider utilise l'API Context pour injecter des données ou services accessibles par tous les descendants sans prop drilling. Correctement utilisé : séparez la logique d'état du Provider (souvent avec useReducer) et exposez un hook consommateur (
useMonContext()).
Évitez de mettre des valeurs qui changent fréquemment dans un Provider large : cela cause des re-rendus massifs. Scindez les contextes par domaine de responsabilité.
Explication :
Avec
renderToPipeableStream, le serveur peut envoyer le HTML progressivement. Les parties enveloppées dans <Suspense> sont remplacées par leurs fallbacks, puis le contenu réel est streamé et remplace le fallback quand il est prêt. L'hydratation est aussi progressive.
Priorisez le contenu important (au-dessus de la ligne de flottaison) et entourez le reste de Suspense pour un LCP (Largest Contentful Paint) optimal.
Explication :
Les composants Headless (comme Headless UI, Radix UI, TanStack Table) fournissent toute la logique (accessibilité, état, interactions) sans imposer de design. Le développeur contrôle entièrement le rendu via des render props ou des hooks.
Cette approche est devenue populaire car elle permet de créer des design systems sur mesure tout en bénéficiant de logiques complexes (combobox, menu, table de données) testées et accessibles.
Explication :
Zustand est un state manager léger qui utilise des fonctions pour créer des stores accessibles via un hook simple. Contrairement à Redux : pas de Provider, pas de reducers obligatoires, support natif des actions asynchrones, pas de boilerplate.
Zustand sélectionne automatiquement une partie du state et ne re-rend que si cette partie change, grâce à des sélecteurs optionnels.
Explication :
React.forwardRef permet de passer une ref à travers un composant enfant. Avec useImperativeHandle, l'enfant peut exposer une API impérative personnalisée au parent (ex: focus(), reset(), scrollToTop()).
À utiliser avec parcimonie : préférez les solutions déclaratives. Les refs impératives sont utiles pour des intégrations avec des bibliothèques non-React ou des animations complexes.
Explication :
SSR (Server-Side Rendering) : le HTML est généré dynamiquement à chaque requête sur le serveur. SSG (Static Site Generation) : le HTML est généré au build et servi comme fichier statique. ISR (Incremental Static Regeneration) est un hybride : régénération périodique.
SSG pour les pages qui changent rarement (blog, docs). SSR pour les contenus dynamiques par utilisateur (dashboard). ISR pour les deux cas avec un délai de fraîcheur configurable.
Explication :
La réactivité fine-grained (SolidJS, Preact Signals, Voby) suit les dépendances au niveau atomique : quand une valeur change, seuls les endroits exacts qui l'utilisent sont mis à jour. Pas de Virtual DOM ni de diffing d'arbre : c'est plus performant. React explore ce concept avec des propositions comme React Forget (compilateur).
Cette différence architecturale explique pourquoi SolidJS est souvent plus rapide que React, bien que React compense par un écosystème plus mature.
Explication :
React Forget (en développement) est un compilateur qui analyse automatiquement le code pour déterminer ce qui doit être mémorisé. Son but : éliminer le besoin d'utiliser manuellement
useMemo, useCallback, et React.memo pour les performances.
Forget n'est pas encore stable, mais il représente la direction future de React : laisser le compilateur gérer les optimisations pour que le développeur se concentre sur la logique métier.