Introduction React et Fonctionnalité
Reactjs est un bibliothèque javascript frontale, elle suit l'approche du composant utilisé pour créer les composants d'interfaces utilisateur réutilisables.
Fonctionnalité du ReactJs
- JSX (Javascript Xml) : il s'agit d'une extension du React qui permet d'écrire le code Javascript similaire au HTML(Cela nous permet d'écrire du HTML dans JavaScript et de le placer dans le DOM sans utiliser de fonctions comme appendChild() ou createElement().
- Virtual DOM : est un objet javascript qui représente en mémoire le vrai DOM(Le DOM virtuel est essentiel pour React car il permet à l'application de mettre à jour l'interface utilisateur en ne modifiant que les éléments qui ont réellement changé. Cela permet d'éviter des mises à jour coûteuses du DOM réel, qui peuvent ralentir les performances de l'application. En utilisant un DOM virtuel, React peut anticiper les mises à jour et cibler efficacement les modifications nécessaires, ce qui améliore les performances globales de l'application.)
(En React, lorsque l'état d'un composant change, React utilise le Virtual DOM pour déterminer les modifications nécessaires au DOM réel et met à jour le DOM de manière sélective, en effectuant uniquement les manipulations nécessaires. Cette approche permet d'améliorer les performances de l'application, car elle évite les manipulations coûteuses et répétées du DOM.)
Concrètement, lorsque le Virtual DOM détecte un changement d'état d'un composant, il crée une nouvelle représentation virtuelle du DOM (appelée Virtual DOM) qui reflète l'état actuel de l'interface utilisateur. Cette nouvelle représentation est comparée avec la représentation précédente, afin de déterminer les différences entre les deux.
Une fois que les différences ont été identifiées, React met à jour le DOM réel en effectuant uniquement les manipulations nécessaires. Par exemple, si un élément de texte a été modifié, React mettra à jour uniquement le contenu de cet élément, plutôt que de reconstruire l'ensemble de la page.
Pour mettre à jour le DOM réel, React utilise des méthodes DOM standard, telles que createElement, appendChild, removeChild, setAttribute, removeAttribute,
React utilise un algorithme de réconciliation pour mettre à jour le DOM réel.
- Composants sont des éléments constitutifs des applications, il divise l'interface utilisateur et petits code indépendants et réutilisables.
Quelles sont les limites de React ?
- React n'est pas un framework à part entière car ce n'est qu'une bibliothèque.
uniDireactionnel data flow
uniDireactionnel data flow : En React, la propagation des données (ou "data flow") est unidirectionnelle. c'est à dire que les données sont transmises d'un composant parent à un composant enfant, mais jamais l'inverse. Cette architecture de données unidirectionnelle facilite la gestion de l'état de l'application et permet d'éviter les effets secondaires imprévus.
DOM virtuel
Le DOM virtuel : est un objet javascript qui représente en mémoire le vrai DOM.Il permet à l'application de mettre à jour l'interface utilisateur en ne modifiant que les éléments qui ont réellement changé. Cela permet d'éviter des mises à jour coûteuses du DOM réel, qui peuvent ralentir les performances de l'application.
Lorsque le state ou props d'un composant React changent, React utilise un processus appelé "réconciliation" pour mettre à jour le DOM virtuel. Cela implique la création d'un nouvel arbre du DOM virtuel qui représente l'interface utilisateur mise à jour, puis la comparaison du nouvel arbre avec l'ancien afin de déterminer les modifications à apporter au DOM réel du navigateur. Une fois que React a déterminé quelles parties du DOM virtuel doivent être mises à jour, il effectue l'ensemble minimal de modifications nécessaires pour mettre à jour le DOM du navigateur, sans avoir à mettre à jour l'ensemble de l'interface utilisateur. Ce processus est beaucoup plus rapide et efficace que la mise à jour directe du DOM du navigateur, car il minimise la quantité de travail que le navigateur doit effectuer. Le DOM virtuel facilite également le raisonnement sur le comportement d'un composant, puisqu'il fournit une séparation nette entre l'état du composant et sa présentation. Cela permet aux développeurs de se concentrer sur l'écriture d'un code propre et modulaire, sans avoir à se préoccuper des détails de la mise à jour de l'interface utilisateur.
Réconciliation
Réconciliation est un mécanisme qui permet de mettre à jour le DOM réel en fonction des changements apportés à l'interface utilisateur.
Le processus de réconciliation est déclenché chaque fois qu'un composant change d'état ou de props. Lorsque cela se produit, React crée une nouvelle représentation virtuelle du DOM, qui reflète l'état actuel de l'interface utilisateur. Cette représentation est comparée avec la représentation précédente pour déterminer les différences entre les deux.
(Pour ce faire, il utilise un algorithme de réconciliation, qui calcule le nombre minimal de manipulations DOM nécessaires pour mettre à jour l'interface utilisateur, en évitant les manipulations coûteuses et répétées.)
L'algorithme de réconciliation est basé sur la méthode de "diffing" (ou comparaison), qui consiste à comparer les nœuds de l'ancien DOM avec les nœuds du nouveau DOM pour déterminer les changements à apporter. Cette technique permet d'optimiser les performances en évitant de re-rendre les parties de l'interface utilisateur qui n'ont pas changé.
Si la reconciliation échoue, React gère les erreurs qui peuvent survenir pendant le rendu d'un composant à l'aide Error Boundaries.
Bonne pratique
- Utiliser des clés stables et uniques pour les listes
- Mises à jour immuables de l'état: Ne mutilez pas les objets/tableaux ; créez de nouvelles références.
- Ne pas mélanger contrôlé / non contrôlé: Un input qui passe de value défini à undefined (ou inversement) déclenche des incohérences.
Diffing
Diffing fait référence à l'algorithme de différenciation qu'utilise React pour identifier les différences entre l'arbre d'éléments virtuels actuel et l'arbre d'éléments virtuels précédent. Cet algorithme permet d' optimiser la mise à jour du DOM réel du navigateur, minimisant le nombre de modifications nécessaires et améliorant les performances de l'application
React Fiber
React Fiber : le moteur de rendu Fiber est basé sur un modèle de traitement asynchrone qui utilise un algorithme de "reconciliation" pour déterminer les mises à jour à effectuer sur l'interface utilisateur. L'algorithme de réconciliation analyse les changements dans l'état des composants et détermine les mises à jour à effectuer de manière incrémentale, en divisant le travail en petites tâches. Cela permet à React de traiter les mises à jour plus rapidement.
Hydratation
L'hydratation consiste à rendre une page interactive après son affichage. Le serveur génère d'abord le HTML. L'utilisateur peut déjà voir la page. Ensuite React télécharge le JavaScript nécessaire et rattache les événements aux éléments affichés.
Par exemple un bouton est visible immédiatement mais il ne devient réellement cliquable qu'après l'hydratation.
L'un des objectifs modernes de Next.js est de réduire la quantité de JavaScript à hydrater. Moins on hydrate, plus l'application est rapide.
Pourquoi moins on hydrate, plus la performance?
Parce que l'hydratation est une opération coûteuse pour le navigateur. Quand une page Next.js est rendue côté serveur, le navigateur reçoit déjà le HTML. Ce HTML peut être affiché immédiatement. Mais ce HTML est uniquement statique. Pour qu'il devienne interactif (boutons, formulaires, événements...), React doit hydrater la page. Cette hydratation comporte plusieurs étapes :
- Télécharger le bundle JavaScript.
- Parser le JavaScript.
- L'exécuter.
- Recréer l'arbre React.
- Comparer cet arbre avec le DOM déjà affiché.
- Attacher tous les événements (onClick, onChange, etc.).
Toutes ces étapes utilisent du CPU. Plus il y a de composants à hydrater, plus le navigateur travaille.
Si Interrompue ou échoué
Si l'hydratation est interrompue, plusieurs problèmes peuvent survenir, car React ne parvient pas à prendre le contrôle complet de l'interface générée côté serveur.
- L'application devient partiellement ou totalement non interactive
Les composants s'affichent bien (grâce au SSR), mais les interactions (clics, formulaires, navigation, etc.) ne fonctionnent pas. Exemple : un bouton est visible mais ne déclenche aucune action au clic.
- Des erreurs de synchronisation DOM peuvent apparaître
React tente de "matcher" l'arbre HTML du serveur avec l'état prévu du client. Si l'hydratation est interrompue ou échoue (ex: à cause d'un décalage de données, de rendu conditionnel, ou d'une erreur JS), React détecte un "mismatch".
Cela peut entraîner : Des warnings dans la console (du type "Text content did not match"). Une reconstruction complète du DOM côté client (ce qu'on essaie justement d'éviter pour des raisons de performance).
Render
Render() est une fonction utilisée pour renvoyer le code HTML qui sera affiché dans le composant. Lorsqu'un composant est créé ou que son state/props change, React appelle la méthode render() pour mettre à jour l'interface utilisateur. La méthode renvoie un élément React, qui est une description de ce qui doit être rendu, y compris le type de composant à rendre et ses propriétés.
Props
Props (propriétés) sont des objets qui stocke les valeurs attributs. Ils ne doivent pas être changés car immutable pour garantir la clarté, la cohérence et la prévisibilité dans une applications
Props Children
Props.children est une props utilisé pour passer du contenu textuel ou des éléments de React en tant qu'enfant, ou Children c'est un moyen de transmettre un contenu qui doit être rendu dans un composant enfant
Render Props (Alternative cloneElement)
Render props" (ou "render props" en anglais) sont une technique pour partager du code entre des composants en passant une fonction en tant que propriété (prop) à un composant enfant. La fonction passée en tant que prop renvoie un élément (ou plusieurs éléments) qui sera affiché à l'écran.
Children Vs Render Props
En React, les "props children" et les "render props" sont deux techniques pour passer des composants en tant que propriétés (props) à un composant parent, mais ils sont utilisés dans des situations différentes.
- Les "props children" sont une technique pour passer des composants enfants à un composant parent en les incluant directement dans la structure JSX. Les "props children" sont souvent utilisés lorsque le composant parent doit envelopper les composants enfants avec des balises HTML supplémentaires ou pour rendre le composant parent plus facile à lire.
- Les "render props" sont une technique pour passer une fonction de rendu en tant que props à un composant parent. La fonction de rendu renvoie un élément (ou plusieurs éléments) qui seront affichés à l'écran. Les "render props" sont souvent utilisés lorsque le composant parent doit transmettre une certaine logique de rendu au composant enfant.
State
State est un objet qui contient des données et des informations sur le composant. Il peut être modifié pendant la durée de vie du composant. Lorsque State change, React rend à nouveau le composant, mettant à jour l'interface utilisateur pour refléter les nouvelles données. On devra toujours utiliser la méthode setState() pour mettre à jour l'état. En effet, React utilise la méthode setState() pour suivre les modifications apportées par le State du composant, et modifier directement l'objet state peut entraîner un comportement inattendu tels que le DOM ne sera pas mis à jour, les effets sécondaires.
Ref
Ref permet d'accéder à un élément DOM sans utiliser target. Les Ref fournissent un moyen d'interagir avec le DOM, sans avoir à utiliser d'autres méthodes telles que findDOMNode() ou à transmettre des props aux composants enfants. Il est créé avec la méthode React.createRef(), qui renvoie un objet Ref. Et l' objet Ref peut ensuite être attaché à un élément React en tant qu'attribut ref).
Conséquence
Rupture avec la philosophie de React: React encourage une approche déclarative pour gérer les interactions avec le DOM et le state. L'utilisation excessive de refs peut introduire une logique impérative qui va à l'encontre de cette philosophie, rendant le code plus difficile à maintenir. Augmentation des risques de bugs: Si les refs sont utilisés dans des situations où React ou un autre composant met aussi à jour l'élément concerné, cela peut entraîner des conflits. Il y a un problèmes de synchronisation
Moments où l'utilisation des refs est appropriée :
- Interactions directes avec le DOM (focus, scroll, animations).
- Stockage de valeurs mutables qui ne nécessitent pas de re-render.
- Intégration de bibliothèques tierces ou manipulation complexe du DOM.
ForwardRef
forwardRef est une fonction qui permet de transférer une référence (ref) à un composant enfant qui n'accepte pas de références en tant que propriété. Le transfert de références est important dans certains cas, par exemple pour gérer le focus d'un élément de formulaire ou pour effectuer des mesures sur des éléments d'interface utilisateur. En général, les références sont transmises à des éléments d'interface utilisateur en utilisant la propriété ref.
Compound Component Pattern
Le pattern Compound Component permet de communiquer entre le composant parent avec ses enfants, en séparant la logique et l'interface utilisateur.
Dans le pattern Compound Component, au lieu de transmettre le state par le props, on transmet les éléments en tant qu'enfants d'un élément parent.
Props Vs State
| ----- | ----- | | Immutable | Mutable | | Permet de transmettre les données d'un composant à un autre en tant qu'argument (Allows data to be passed from one component to another as an argument) | Contient les informations sur les composants (Contains information on the components) | | Le composant d'enfant peut accéder aux props (The child component can access the props) | N'est pas accessible aux composants d'enfant (Not accessible to the child's components) |
Composants Fonctionnels
Ce sont des fonctions JavaScript qui acceptent des props comme arguments et retournent du JSX pour définir l'interface utilisateur.
Ils utilisent les hooks (useState, useEffect, etc.) pour gérer l'état ou les effets de cycle de vie.
Composant Classe
Ce sont des classes ES6 qui étendent React.Component et implémentent une méthode render pour retourner du JSX. Ils gèrent le state en tant que propriété interne. Ils fournissent des méthodes de cycle de vie comme componentDidMount, componentDidUpdate, etc.
Fonctionnels Vs Classe
Le composant fonctionnel permet d'utiliser des hooks pour ajouter des fonctionnalités comme l'état ou les effets. Le composant classe, les hooks ne sont pas utilisables avec les composants de classe.
Le composant fonctionnel est défini comme des fonctions JavaScript simples. Le composant classe est basés sur des classes ES6 étendant React.Component.
Composants Contrôlés
Le composants contrôlé: c'est un composant dont la source de vérité (la valeur affichée et son évolution) est gérée par React, via son state ou via des props provenant d'un parent.
Dans le cas des formulaires :
- La valeur de l'input est liée à une variable de state.
- Toute mise Ă jour passe par un handler qui modifie ce state.
- L'UI reflète toujours l'état actuel.
Inconvénient : plus de re-renders → peut être coûteux si le formulaire est énorme (optimisation possible avec useMemo / React.memo)
Controlled Components
Composants Non Contrôlés
Les composants non contrôlés : c'est un composant dont la valeur n'est pas gérée par React, C'est le DOM qui garde l'état interne (par ex. la valeur d'un \<input>). On utilise une ref pour lire ou modifier le valeur seulement quand on en a besoin via ref.current.value. Inconvénients :
- Pas de synchronisation en temps réel avec React.
- Validation et mise à jour de l'UI plus compliquées.
- Difficile Ă tester car il faut manipuler le DOM.
Uncontrolled Components
Composants Stateful
Un composant Stateful est un composant qui gère un state interne, c'est-à -dire des données qui peuvent changer au fil du temps. Il contient souvent une logique métier ou des interactions avec l'utilisateur qui nécessitent de modifier l'état.
Composants Stateless
Un composant Stateless est un composant qui ne gère pas d'état interne (state).il se contente de recevoir des props et de les afficher. Il est souvent utilisé pour des composants "présentationnels" (pure UI), car il ne contient que de la logique d'affichage.
Différence entre Hook et classe
- Pas de class et donc pas de keyword class, pas d'instanciation et donc on ne s'embĂŞte pas avec de la logique de class js.
- Pas de constructor (No the contructor)
- Pas de this (ça peut faire éviter quelques bugs)
- Beaucoup plus simple à lire et donc à débugger. (On évite le code verbeux des class)
- Une manipulation beaucoup plus simple et performante des événements et changements de props.
- Hook est utilisé dans les composants fonctionnels de React.
- Classe est dans les composants basés sur les classes de React.
- Hook n'a pas encore introduit certaines fonctions tels que : — getSnapshotBeforeUpdate() — getDerivedStateFromError() — componentDidCatch()
Voir \=> [Pourquoi on utilise HOOk que classe](https://oclock.io/blog/4708/pourquoi-se-former-aux-hooks-de-react#:~:text=Les%20hooks%20sont%20la%20nouvelle,utilisation%20d'%C3%A9tat%20local)
PureComponent
PureComponent est une classe qui possède déjà sa méthode ShoudComponentUpdate qui se charge d'effectuer une comparaison de surface et l'état local. C'est-à -dire qu'il compare les valeurs lors de la recherche de type de données primitifs et compare les références d'objets.
L'utilisation Purecomponent :
State/Props du composant est un objet immuable State / Props ne doit pas avoir l'objet imbriqué à plusieurs niveaux
Conseils Pro : Tous les composants enfant de PureComponent doivent également être des composants purs ou fonctionnels.
Higher Order Component (HOC)
HOC (Composant d'ordre Supérieur) est une fonction qui accepte un composant et renvoie un nouveau composant.
Lors du développement, il est courant de créer des composants qui partagent des comportements ou une logique similaire. Pour éviter de répéter du code et respecter le principe DRY ("Don't Repeat Yourself"), il est important de trouver une abstraction permettant de centraliser cette logique dans un seul endroit et de la partager entre les composants. Le HOC est une solution idéale pour créer cette abstraction, en encapsulant la logique réutilisable et en l'appliquant à plusieurs composants.
Key et importance
Importance of keys
- Keys aident à identifier les éléments qui ont été ajoutés, modifiés ou supprimés.
- Sans Keys, React ne comprend pas l'ordre ou l'unicité de chaque élément.
Éviter
L'index du tableau change dès qu'on insère/supprime/tri/re-filtre → React associe le mauvais composant au mauvais item, ce qui crée des bugs d'état.
Duplication de keys
Avec des keys dupliquées, React ne sait plus quelle instance correspond à quel item : l'état se mélange, et la suppression peut viser le mauvais élément.
LifeCycle de composant
Cycle de vie de composant
- Constructor()
- Render()
- ComponentDidMount()
- ShouldComponentUpdate()
- Render()
- ComponentDidUpdate()
Component phase
Les Phases de composant
- Montage (Mounting) : Cette étape se produit lorsque le composant est créé et ajouté à l'arbre de composants React. Les méthodes de cycle de vie correspondantes sont : constructor(), getDerivedStateFromProps(), render(), et componentDidMount().
- Mise à jour (Updating) : Cette étape se produit chaque fois que le composant est mis à jour, généralement en réponse à une modification des propriétés (props) ou de l'état (state) du composant. Les méthodes de cycle de vie correspondantes sont : getDerivedStateFromProps(), shouldComponentUpdate(), render(), getSnapshotBeforeUpdate(), et componentDidUpdate().
- Démontage (Unmounting) : Cette étape se produit quand le composant est retiré de l'arbre de composants React, parce qu'il n'est plus nécessaire ou que son parent est lui-même retiré. La méthode de cycle de vie correspondante est : componentWillUnmount().
Fragment
Fragment permet de regrouper la liste de plusieurs enfants sans ajouter un nœud supplémentaire du DOM. Un fragment est utile lorsqu'on a besoin d'ajouter plusieurs éléments enfants à un composant, mais que on ne veut pas ajouter un élément parent supplémentaire dans le DOM, qui pourrait affecter la structure et le style de la page. fragment peut aussi améliorer les performances de l' application en évitant la création d'éléments DOM inutiles.
ProtoType
En React, PropTypes est une validation de type pour les props (propriétés) qui permet de définir les types de données attendus pour chaque prop d'un composant. PropTypes permet de vérifier que les données transmises à un composant correspondent au type de données attendu, et de fournir des messages d'erreur clairs si ce n'est pas le cas
React Hooks
What are React Hooks
Hooks ont un nouvel ajout à React dans la version 16.8 qui vous permet d'utiliser l'état et d'autres fonctionnalités de React, comme les méthodes de cycle de vie, sans écrire de classe.
Les Hooks sont des functions qui permettent de bénéficier de fonctionnalités React qu'on pouvait avoir que via une classe : Ex un state local, les cycles de vie, les contextes, etc.
- Hook permet de refactorer des composants complexes et Ă tester.
- Hook supprime la complexité inhérente de classe telle que l'initialisation de constructeur et les fonctions de liaison aux composants pour ses méthodes y aient accès dans l'instance de composant
- Hook nous permettent d'organiser la logique à l' intérieur d' un composant en unités réutilisables et isolées .
- Rules - Règles à suivre lors de l'utilisation de React Hooks ?
- React Hooks doit être appelé uniquement au niveau supérieur. Il n'est pas permis de les appeler à l'intérieur des fonctions, boucles ou conditions imbriquées.
- Il est autorisé d'appeler les crochets uniquement à partir des composants de la fonction Reactjs
- Basic React Hooks
Règles Hook
- Toujours en haut
- Toujours dans un composant ou hook
- Jamais dans condition / boucle
Pourquoi "jamais dans une condition ou boucle" ? Parce que React identifie les hooks uniquement par leur ordre d'appel, pas par leur nom.
UseState
UseState est un Hook en React qui permet d'avoir des variables d'état dans les composants fonctionnels. Il permet de créer un état interne dans une fonction, ce qui permet de stocker des données qui peuvent être modifiées et qui peuvent déclencher un nouveau rendu du composant. Le state est une donnée interne au composant qui peut être modifiée par le biais de la fonction retournée par useState.
const [state, setState] \= useState(initialState);
UseEffect
UseEffet qui permet de gérer les effets de bord dans les composants fonctionnels
Le but est d'exécuter la logique des side-effects à l'intérieur de la fonction de callback qui utilise l'argument des dépendances pour contrôler quand on souhaite que side-effects s'exécute.
UseEffet permet de gérer le cycle de vie de composant comme à une combinaison de ComponentDidMount, componentDidUpdate, et componentWillUnmount. useEffect(callback[, dependencies]); Si les dépendances ne sont pas fournies, le side-effects s'exécute après chaque rendu. S'il s'agit d'un tableau vide [], le side-effects s'exécute une fois après le rendu initial.
useEffect(callback[, dependencies]);
Il existe deux types :
- Effects sans Cleanup
- Effects avec Cleanup
UseLayoutEffect
C'est similaire qu'à useEffect(), la différence qu'il s'exécutera après que React a validé les mises à jour du DOM. Il est utilisé dans de rares cas, lorsqu'on veut calculer la distance entre les éléments après une mise à jour ou effectuer d'autres calculs
UseContext
Le contexte fournit un moyen de transmettre des données à travers l'arborescence des composants sans avoir à transmettre les props manuellement à chaque niveau.
Le Contexte est basé sur deux composants:
- Provider: permet de fournir les données du contexte
- Consumer: permet de les récupérer.
- Provider
- Consumer.
Avantages :
- Solution native à la librairie React, elle est disponible dès que l'on commence une nouvelle application React
- Prise en main très facile
- Il est possible d'intégrer des contextes plus "locaux", c'est-à -dire qui n'englobent pas l'intégralité de l'application mais plutôt une petite quantité de composants : cela permet de segmenter la logique de l'application
Inconvénients :
- L'API Context n'est pas adaptée pour des changements fréquents de state (par exemple, pour la valeur d'un champ de texte)
- Tous les composants consommant le contexte vont être re-render à chaque changement du stage global proposé par le contexte, même si l'information qu'ils utilisent n'est pas changée
UseCallback
useCallback renverra une version mémorisée du Callback qui ne change que si l'une des dépendances a changé. Ceci est utile lors de la transmission de callback à des composants enfants optimisés qui reposent sur l'égalité des références pour éviter les rendus inutiles.
UseCallback permet de mémoriser callback des fonctions, afin qu'elles ne soient pas recréées à chaque nouveau rendu.) Il est similaire à useMemo, sauf qu'il renvoie une fonction et useMemo renvoie une valeur.
const memoizedCallback \= useCallback( () \=> { doSomething(a, b); }, [a, b], );
UseMemo
useMemo recalculera la valeur mémoïsée seulement si une des entrées a changé. Cette optimisation permet d'éviter des calculs coûteux à chaque rendu.
const memoizedValue \= useMemo(() \=> computeExpensiveValue(a, b), [a, b]);
Pourquoi useMemo partout est une mauvaise idée ?
Parce que useMemo consomme aussi de la mémoire et ajoute une logique supplémentaire. Si le calcul est simple, le coût du mémo peut être supérieur au coût du recalcul.
UseMemo Vs UseCallBack
useMemo et useCallback sont deux hooks utilisés pour optimiser les performances des composants fonctionnels useMemo : Mémorise et retourne une valeur useCallback : Mémorise et retourne une fonction
UseMemo et React.Memo
useMemo et React.memo qui permettent d'optimiser les performances de l'application en réduisant le nombre de rendus inutiles. useMemo est un hook qui permet de "mémoriser" (c'est-à -dire de mettre en cache) le résultat d'un calcul coûteux et de ne le recalculer que lorsque les dépendances ont changé. useMemo est souvent utilisé pour éviter de recalculer des valeurs dérivées à chaque fois qu'un composant est rendu.
React.memo est une fonction qui permet de "mémoriser" un composant et d'éviter de le rendre à nouveau s'il reçoit les mêmes props. React.memo est souvent utilisé pour éviter des rendus inutiles de composants qui n'ont pas changé.
Pourquoi React.memo n'est pas une solution miracle ?
Parce qu'il ajoute lui aussi un coût de comparaison des props. Je l'utilise uniquement lorsqu'un composant est coûteux à rendre et que ses props sont relativement stables. Je mesure avant d'optimiser.
UseRef
Chaque fois qu' on met à jour un state local ou un props, le composant s'affiche à nouveau pour afficher les derniers éléments en fonction de la mise à jour de l'état. Afin d'aborder le re-rendu du composant, on utilise une variable locale via useRef hook. useRef renvoie un objet ref, dont la .current propriété est initialisée à l'argument passé ( initialValue). L'objet renvoyé persistera pendant toute la durée de vie du composant.
const refContainer \= useRef(initialValue);
useState Vs UseRef
useState met à jour l'UI en déclenchant un re-render, tandis que useRef stocke une valeur sans provoquer de re-render.
CreateRef Vs UseRef
useRef et createRef sont deux méthodes pour créer des références à des éléments d'interface utilisateur en React. createRef est utilisé dans les composants de classe, tandis que useRef est utilisé dans les composants fonctionnels. useRef renvoie également la même instance d'objet pour chaque rendu, tandis que createRef crée une nouvelle instance à chaque appel.
UseImperativeHandle
useImperativeHandle c'est un hook qui permet à un composant fonctionnel d'exposer des méthodes ou des propriétés personnalisées à son parent lorsqu'il est utilisé avec une ref. Il est utilisé en combinaison avec React.forwardRef.
Props Drilling
Parfois, lors du développement d'applications React, il est nécessaire de transmettre des données d'un composant situé plus haut dans la hiérarchie à un composant profondément imbriqué. Pour transmettre des données entre de tels composants, on transmet via props à partir d'un composant source et continuons à transmettre props au composant suivant dans la hiérarchie jusqu'à ce qu'on atteint le composant profondément imbriqué.
Error boundaries
Introduites dans la version 16 de React, Error boundaries nous permettent de détecter les erreurs qui se produisent lors de la phase de rendu. Error boundaries est un composant utilisant l'une ou les deux méthodes suivantes : static getDerivedStateFromError et componentDidCatch.
Portal
Les portails pour afficher des composants enfants dans un nœud DOM qui existe en dehors de la hiérarchie DOM du composant parent (ReactDOM.createPortal(child, container)
Redux
Redux est une bibliothèque pour la gestion d'état dans les applications React. Elle fournit un moyen de stocker et de gérer l'état global de l'application, qui peut être partagé entre différents composants.
Redux utilise un store centralisé pour stocker l'état global de l'application, qui peut être accédé à partir de n'importe quel composant. Les données dans le store ne peuvent être modifiées que par des "actions", qui sont envoyées au store. Ces actions sont des objets simples qui décrivent un changement souhaité avec un type et, parfois, des données supplémentaires.
Le store met à jour l'état de l'application en fonction de l'action reçue à l'aide de "reducers".
Les reducers sont des fonctions pures qui prennent l'état actuel et une action comme arguments et renvoient un nouvel état. Chaque reducer gère une partie spécifique de l'état global de l'application. Lorsqu'une action est dispatchée et que l'état est mis à jour, le store déclenche un nouveau rendu des composants qui dépendent de cet état.
[Liens schema architectu](https://www.linkedin.com/pulse/redux-architecture-overview-priyesh-chandra-1c/)re
Fonctionnement du Redux( How does Redux work)
Redux génère l'objet javascript appelé le store Store contient le globale State de composant Actions qui représentent les différentes interactions que l'utilisateur peut faire, il s'agit de déclencheur. Enfin les actions se transmettent dans les Reducers qui définissent les actions du State
Dispatch
Les actions sont envoyées au Store à l'aide de la méthode dispatch(). Lorsqu'une action est envoyée, elle est transmise au Reducer, qui déterminent comment mettre à jour l'état de l'application.
Connect
Dans Redux, connect est une fonction fournie par la bibliothèque react-redux qui permet aux composants React de se connecter au Store Redux.
La fonction connect est utilisée pour créer des composants d'ordre supérieur (HOC) qui enveloppent un composant de base et lui fournissent un accès au Store Redux. Elle prend deux arguments : mapStateToProps et mapDispatchToProps.
- mapStateToProps est une fonction qui prend l'état actuel du magasin et le met en correspondance avec les props du composant enveloppé. Elle renvoie un objet qui spécifie les parties de l'état qui doivent être transmises au composant.
- mapDispatchToProps est une fonction facultative qui fait correspondre les créateurs d'actions aux props. Elle peut être utilisée pour simplifier le processus de distribution des actions vers le magasin.
3 règles ou principaux du redux
- Le global state est unique
- Le state est en lecture seule (si on modifie le state, on doit passer par l'Actions. Sinon redux ne sera pas que ça n'a pas changé, il y a une forte chance que le Framework ne redésigne pas la vue et c'est pas traçable)
- Reducers sont des fonctions pures ( car le reducers sont des fonctions qui collent les changements et ne doivent pas prendre en compte des effects de bord, pas des requêtes ajax dépendante du temps, le Reducers ne fait que du synchrone)
CombineReducer
CombineReducer est une fonction qui permet de combiner plusieurs Reducers en un seul Reducer root. Le Reducer root est ensuite utilisé pour créer le store de l'application. L'utilité de combineReducers est de diviser la gestion de l'état de l'application en plusieurs Reducer spécialisés, chacun étant responsable de gérer une partie spécifique de l'état. Cela permet de séparer les préoccupations et de faciliter la compréhension et la maintenance du code.
ApplyMiddleWare
applyMiddleware est une fonction qui permet d'appliquer des middleware à un store Redux. Les middleware sont des fonctions qui sont exécutées à chaque fois qu'une action est dispatchée vers le store. L'utilité de applyMiddleware est de permettre la gestion des actions asynchrones et la mise en place de traitements additionnels lors de la réception d'une action. Les middleware peuvent intercepter les actions avant qu'elles n'atteignent les Reducers, et effectuer des tâches telles que la gestion de requêtes asynchrones, la journalisation, le traitement de la logique métier, la surveillance de l'état de l'application,
Asynchrone avec Thunk & promise([VOIR PLUS)](https://redux.js.org/tutorials/fundamentals/part-6-async-logic)
En Redux, les requêtes asynchrones peuvent être traitées à l'aide de middleware tels que "redux-thunk" ou "redux-saga". L'architecture typique pour traiter les requêtes asynchrones en Redux consiste à créer trois types d'actions pour chaque requête : une action de demande, une action de succès et une action d'échec.
Avantages :
- Architecture des responsabilités (reducers, actions, …) bien définie et constante
- Des extensions de navigateur comme "Redux DevTools" sont disponibles et permettent de facilement débugger l'intégration de Redux dans un projet utilisant React
Inconvénients :
- Difficile à adopter lorsqu'on débute sur React
- Librairie externe à React : les deux packages nécessaires (redux & react-redux) représentent des données supplémentaires à télécharger pour l'utilisateur final
Redux Vs ApiContext
Le choix entre Redux et Context API dépend de la taille et de la complexité de l'application, ainsi que des préférences de développement de l'équipe. Pour les applications de grande envergure nécessitant une gestion d'état robuste, Redux est souvent le choix privilégié. Pour les applications plus petites à modérées, et quand on évite la complexité supplémentaire, l'API Context pourrait être suffisante.
- Performance : Redux peut conduire à une meilleure performance pour les grandes applications car il optimise les mises à jour d'état et peut éviter des rendus inutiles, tandis que l'API Context peut causer des rendus supplémentaires si elle n'est pas implémentée avec précaution.
- Complexité : Redux a une courbe d'apprentissage plus raide et peut surcompenser pour des applications plus petites, tandis que l'API Context est plus facile à apprendre et à intégrer.
Je pars du plus simple. Pour un état global limité (thème, langue, user) et peu de mises à jour, Context suffit.
Dès qu'on a un état volumineux/partagé, des updates fréquentes, des middlewares ou besoin d'un outillage solide (DevTools, time-travel, normalisation), Redux devient plus pertinent. Côté perf, Redux limite mieux les rerenders via des sélecteurs, alors que Context doit être découpé pour ne pas tout rerendre.
Redux-thunk Vs saga
redux-thunk et redux-saga sont deux middlewares de Redux qui permettent de gérer des opérations asynchrones dans une application. Ils ont des approches différentes pour résoudre le même problème: comment interagir avec l'API et effectuer des effets secondaires en gardant les principes de Redux.
- Complexité: Redux-Saga est plus complexe à comprendre, surtout pour les développeurs moins familiers avec les fonctions générateurs de JavaScript, tandis que Redux-Thunk utilise des fonctions qui retournent des fonctions, ce qui est généralement plus simple.
- Testabilité: Redux-Saga est souvent loué pour la facilité de test de ses sagas grâce aux effets déclaratifs, contrairement aux thunks qui nécessitent de mocker les dispatch et getState.
Mode Strict
StrictMode est un outil ajouté dans la version 16.3 de React pour mettre en évidence les problèmes potentiels dans une application. Il effectue des vérifications supplémentaires sur l'application.
StrictMode aide actuellement avec les problèmes :
- Identification des composants avec des méthodes de cycle de vie non sécurisées
- Avertissement sur l'utilisation de findDOMNode
- Avertissement concernant l'utilisation de l'API contextuelle héritée (car l'API est sujette aux erreurs).
Concurrent Mode
Le Concurrent Mode est une fonctionnalité de React 18 qui permet à plusieurs mises à jour de l'interface utilisateur de se faire simultanément. Cela permet à React de travailler sur plusieurs tâches en même temps, interrompre et reprendre ces tâches sans bloquer le fil principal du navigateur, ce qui améliore significativement la fluidité et la réactivité des applications. Pour utiliser le Concurrent Mode, on devra l'activer dans l' application React.
Optimisation React
Pour optimiser les performances de l'application React
- Utilisation de useMemo( )
- Utilisation de React.PureComponent
- Lazy Loading
Performance React
Pour obtenir la version de production la plus efficace avec Brunch, installez l'extension [terser-brunch](https://github.com/brunch/terser-brunch) :
- Brunch- Browserify
- Rollup-webpack
Éviter la réconciliation Pour éviter la création de nœuds DOM superflus et l'accès excessif aux nœuds existants, dans la mesure où ces opérations sont plus lentes que sur des objets JavaScript.
Quand les props ou l'état local d'un composant changent, React décide si une mise à jour du DOM est nécessaire en comparant l'élément renvoyé avec l'élément du rendu précédent. Quand ils ne sont pas égaux, React met à jour le DOM.
Même si React ne met à jour que les nœuds DOM modifiés, refaire un rendu prend un certain temps. Dans la plupart des cas ce n'est pas un problème, mais si le ralentissement est perceptible, vous pouvez accélérer le processus en surchargeant la méthode shouldComponentUpdate du cycle de vie, qui est déclenchée avant le démarrage du processus de rafraîchissement. L'implémentation par défaut de cette méthode renvoie true, laissant ainsi React faire la mise à jour
Si vous savez que dans certaines situations votre composant n'a pas besoin d'être mis à jour, vous pouvez plutôt renvoyer false depuis shouldComponentUpdate afin de sauter le rendu, et donc l'appel à la méthode render() sur ce composant et ses enfants. Le plus souvent, plutôt que d'écrire manuellement shouldComponentUpdate(), vous pouvez plutôt choisir d'étendre [React.PureComponent](https://fr.reactjs.org/docs/react-api.html#reactpurecomponent). Ça revient à implémenter shouldComponentUpdate() avec une comparaison superficielle des propriétés et état actuels et précédents.
Données immuables
On évite de modifier directement les valeurs que vous utilisez dans les props ou l'état local
ES6 offre la [syntaxe de décomposition](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Syntaxe_d%C3%A9composition) (spread operator, NdT) pour les tableaux, ce
qui facilite ce type d'opération. Si vous utilisez Create React App, cette syntaxe est disponible par défaut.
En évitant de modifier l'objet original, nous pouvons utiliser la méthode [Object.assign](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Object/assign) :
[La syntaxe de décomposition des objets](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Syntaxe_d%C3%A9composition) facilite la mise à jour d'objets sans pour autant les modifier :
Virtualiser les listes longues Si votre application génère d'importantes listes de données (des centaines ou des milliers de lignes), nous vous conseillons d'utiliser la technique de « fenêtrage » (windowing, NdT). Cette technique consiste à n'afficher à tout instant qu'un petit sous-ensemble des lignes, ce qui permet de diminuer considérablement le temps nécessaire au rendu des composants ainsi que le nombre de nœuds DOM créés.
[react-window](https://react-window.now.sh/) et [react-virtualized](https://bvaughn.github.io/react-virtualized/) sont des bibliothèques populaires de gestion du fenêtrage.
Mémorisation des composant React
La mémorisation est une technique d'optimisation en stockant les résultats d'appels de fonction et en renvoyant le résultant mis en cache lorsque les mêmes entrées se reproduisent. Une fonction mémorisée est généralement plus rapide car si la fonction est appelée avec les mêmes valeurs que la précédente, au lieu d'exécuter une logique de fonction, elle récupère le résultat du cache
Element Vs Component
En React, un élément (Element) et un composant (Component) sont deux concepts différents.
Un élément (Element) est un objet JavaScript qui décrit ce que l'on souhaite afficher à l'écran. Il peut être créé en utilisant la syntaxe JSX ou en utilisant la fonction React.createElement(). Les éléments sont des objets immuables qui représentent l'interface utilisateur et ne peuvent pas être modifiés une fois qu'ils ont été créés.
Un composant (Component) est une fonction ou une classe qui peut prendre des propriétés (props) en entrée et renvoyer un élément (Element) en sortie. Les composants peuvent être réutilisables et modulaires, et ils sont utilisés pour décrire l'interface utilisateur de manière déclarative.
Presentational and Container component
Presentational and Container component est utilisée en React pour séparer les responsabilités de présentation et de gestion de l'état d'un composant.
Un composant de présentation est responsable de la présentation de l'interface utilisateur. Il ne contient pas de logique métier ou de gestion d'état complexe. Les composants de présentation sont des composants fonctionnels et sont souvent réutilisables.
Un composant de conteneur, en revanche, est responsable de la logique métier et de la gestion de l'état d'un composant. Il peut encapsuler un ou plusieurs composants de présentation et fournir des données et des fonctions pour les manipuler.
L'avantage de cette pattern est qu'elle permet de séparer les responsabilités de présentation et de gestion de l'état d'un composant, ce qui facilite la réutilisation et la maintenance du code. Les composants de présentation peuvent être réutilisés dans d'autres composants de conteneur, tandis que les composants de conteneur peuvent être spécialisés pour différents cas d'utilisation.
Suspense
React Suspense est une fonctionnalité dans React 16.6 pour gérer l'état de chargement asynchrone des composants dans une application React. Elle permet de suspendre le rendu d'un composant jusqu'à ce que toutes les dépendances asynchrones (telles que le chargement de données à partir d'une API) soient résolues. Avant l'introduction de React Suspense, les développeurs devaient gérer manuellement l'état de chargement et les erreurs lors de l'utilisation de données asynchrones dans leurs composants. Cela nécessite souvent l'utilisation de techniques telles que les callbacks, les promesses (promises) ou les bibliothèques externes. Lorsque vous utilisez des composants asynchrones tels que React.lazy (pour le chargement paresseux des composants) ou ReactDOM.createRoot (pour le rendu racine), React Suspense peut détecter automatiquement quand une partie de l'interface utilisateur est en attente de données et afficher un indicateur de chargement pendant ce temps.
Pourquoi plusieurs Suspense sont souvent meilleurs qu'un seul ?
Je veux éviter qu'une ressource lente bloque toute l'expérience utilisateur. Je préfère que chaque section devienne indépendante.
Batch State
React batch est un mécanisme interne de React qui permet de regrouper plusieurs mises à jour d'état en une seule opération de re-rendering.
Si on clique sur la fonction handleClick, le composant se rechargera une seule fois. Cela est dû au fait que les trois fonctions de mise à jour de l'état (SetName, SetLastName, SetFirstName) sont appelées de manière consécutive dans la fonction, et React regroupe les mises à jour d'état avant de déclencher un seul rechargement du composant. Par conséquent, même s'il y a trois mises à jour d'état, elles seront regroupées et entraîneront un seul rechargement du composant.
onClick={ \=> X} et onClick={X}
onClick={() \=> X()} : Dans cette approche, une fonction fléchée est utilisée comme callbacl onClick. Lorsque l'événement onClick se produit, la fonction fléchée est invoquée en tant que nouvelle fonction à chaque fois. Cela signifie que chaque rendu du composant crée une nouvelle instance de la fonction. Cela peut entraîner des problèmes de performances si la fonction est utilisée dans un composant avec un rendu fréquent, car une nouvelle fonction doit être créée à chaque fois, ce qui peut avoir un impact sur les performances et la consommation de mémoire.
onClick={X} : Dans cette approche, la référence à la fonction X elle-même est utilisée comme rappel onClick. Lorsque l'événement onClick se produit, la fonction X est invoquée directement. La référence à la fonction n'est pas modifiée à chaque rendu du composant. Cela peut être plus efficace en termes de performances, car la même référence à la fonction est utilisée à chaque fois, évitant ainsi la création de nouvelles fonctions à chaque rendu.
SPA
SPA est une implémentation d'application web qui ne charge qu'un seul document web, puis met à jour le contenu du corps de ce document via des API JavaScript telles que [XMLHttpRequest](https://developer.mozilla.org/fr/docs/Web/API/XMLHttpRequest) et [Fetch](https://developer.mozilla.org/fr/docs/Web/API/Fetch_API) lorsqu'un contenu différent doit être affiché. Cela permet aux utilisateurs d'utiliser des sites web sans charger de nouvelles pages entières à partir du serveur, ce qui peut entraîner des gains de performances et une expérience plus dynamique, avec certains inconvénients tels que le référencement (SEO), plus d'efforts nécessaires pour maintenir l'état, mettre en œuvre la navigation et mesurer les performances.
Code splitting
code splitting consiste à séparer le code en plusieurs paquets ou composants qui peuvent être chargés à la demande ou en parallèle. c'est-à -dire qu'ils ne sont pas chargés tant qu'ils ne sont pas nécessaires. Les avantages du code spitting sont : La vitesse de chargement du site devient plus rapide. Le temps d'interaction s'améliore.
En react pour effectuer code splitting:
- Avec React.Lazy : Cette fonction vous permet d'importer un composant de manière dynamique et de l'insérer dans un composant Suspense
- Séparation de route avec React Router : en séparant le code par route
Déclaration Style CSS
L'utilisation du CSS avec React peut se faire de plusieurs manières:
Standard CSS: Il faut juste d'importer une feuille de style CSS dans un fichier de composant
Avantages: C'est la méthode traditionnelle et la plus connue par les développeurs. Séparation des préoccupations : Le CSS est séparé du JavaScript, ce qui peut être plus lisible pour certains développeurs. Facilité d'utilisation : Il n'y a pas besoin d'apprendre de nouvelles syntaxes ou méthodologies.
Inline CSS: Inline CSS est souvent écrit sous forme d'objet JavaScript, où les propriétés CSS sont appliquées directement sur l'élément JSX
Avantages: Portée locale : Le style ne s'applique qu'à l'élément sur lequel il est placé, évitant ainsi les conflits. Contrôle dynamique : Il est facile d'altérer les styles en fonction de l'état ou des props du composant.
CSS Modules
CSS Modules permettent de créer des fichiers CSS qui sont transformés en un objet où les classes ont des noms locaux uniques. Vous les utilisez en important le fichier CSS comme un module dans votre composant JavaScript.
Avantages: Portée locale par défaut : Évite les conflits de nom de classe et l'effet de cascade involontaire. Composition : Permet de composer les styles en combinant différentes classes.
Styled Components
Styled Components
Styled Components permet de créer des composants React avec des styles attachés, en utilisant des chaînes de caractères taguées pour le CSS.
Avantages:
- Styles encapsulés : Les styles sont attachés spécifiquement aux composants, réduisant les conflits et l'effet de cascade.
- JavaScript et CSS en un seul endroit : Favorise la cohésion en gardant la logique et les styles ensemble.
- Thème et props : Les styles peuvent être facilement thématisés et modifiés en fonction des props.
Automatic Batching
Avantage : L'automatisation du regroupement des mises à jour dans React 18 permet de réduire le nombre de rendus inutiles et améliore ainsi les performances. Cela signifie que plusieurs mises à jour d'état peuvent être combinées en une seule, réduisant ainsi les re-rendus de composants. Problème résolu : Avant React 18, les mises à jour d'état asynchrones (comme celles dans les promesses, les timeouts, etc.) n'étaient pas toujours regroupées automatiquement. Cela pouvait entraîner des re-rendus multiples pour chaque mise à jour d'état, diminuant ainsi les performances.
Suspense sur le server
Avantage : L'introduction de Suspense sur le serveur permet de retarder le rendu de certaines parties de l'interface jusqu'à ce que toutes les données nécessaires soient disponibles. Cela améliore l'expérience utilisateur en réduisant les temps de chargement perçus, et rend possible le streaming du HTML au client. Problème résolu : Avant cette fonctionnalité, les applications Server-Side Rendering (SSR) attendaient que toutes les données soient prêtes avant d'envoyer une page complète au client. Cela pouvait entraîner des temps de chargement plus longs. Avec Suspense sur le serveur, les applications peuvent envoyer des parties du HTML avant que toutes les données ne soient disponibles, améliorant ainsi le rendu progressif.
Server component et client Component
Avantage : React introduit la distinction entre les composants serveur et client, permettant aux composants de fonctionner soit sur le serveur (où le JavaScript n'est pas nécessaire), soit sur le client (pour des interactions côté client). Cela réduit la quantité de JavaScript envoyé au navigateur, optimisant les performances. Problème résolu : Avant cette fonctionnalité, tous les composants React devaient être rendus côté client, même ceux qui n'avaient pas d'interactions directes avec l'utilisateur, ce qui augmentait la taille des bundles JavaScript. Désormais, les composants qui n'ont pas besoin d'être interactifs peuvent rester sur le serveur.
useId
Avantage : Le hook useId permet de générer des identifiants uniques, qui sont cohérents entre le serveur et le client. Cela est crucial pour les scénarios où des composants nécessitent des identifiants uniques pour les attributs comme aria-*, id dans des formulaires, ou des éléments interactifs. Problème résolu : Avant useId, générer des identifiants uniques à la fois côté serveur et côté client pouvait entraîner des problèmes de dé-synchronisation, notamment dans le rendu SSR où les identifiants générés côté serveur pouvaient différer de ceux générés côté client, causant des erreurs de réhydratation.
useTransition
Avantage : useTransition permet de différer certaines mises à jour pour qu'elles soient considérées comme « non urgentes », ce qui aide à maintenir une interface utilisateur fluide. Cela permet par exemple de prioriser les interactions immédiates (comme les clics ou les saisies) tout en retardant des mises à jour moins cruciales, comme le chargement de données. Problème résolu : Dans les versions antérieures de React, toutes les mises à jour d'état avaient la même priorité, ce qui pouvait entraîner des blocages dans l'interface utilisateur lorsque des opérations coûteuses étaient effectuées, rendant l'expérience utilisateur moins réactive.
useSyncExternalStore
Avantage : Ce hook standardise la manière dont les composants peuvent se synchroniser avec des stores d'état externes (comme Redux, Zustand, etc.). Il permet de garantir que l'état du store externe est correctement synchronisé avec React et améliore la compatibilité avec les rendus concurrents. Problème résolu : Auparavant, chaque bibliothèque externe gérait cette synchronisation de manière différente, ce qui pouvait entraîner des comportements imprévisibles ou inefficaces, notamment avec les nouvelles fonctionnalités comme le mode concurrent. useSyncExternalStore assure une meilleure intégration avec l'architecture concurrente de React.
Webpack
Webpack est un outil de développement utilisé pour le bundling (ou empaquetage) de fichiers JavaScript pour les applications. Il nous aider à gérer les dépendances et à optimiser le code pour les déploiements en production
Il prend les fichiers JavaScript et leurs dépendances (comme des modules ES6, CommonJS, ou AMD) et les combine en un ou plusieurs bundles. Un bundle est un seul fichier ou un groupe de fichiers qui peuvent être chargés par le navigateur.
Gestion des Dépendances : Webpack analyse les dépendances de votre projet. Il suit les relations entre les fichiers pour comprendre comment ils sont connectés. Cela inclut non seulement le JavaScript, mais aussi les CSS, les images, les polices, et même les fichiers HTML.
Transformation de Fichiers : Webpack utilise des loaders pour transformer les fichiers. Par exemple, Babel peut être utilisé pour transpiler du code JavaScript ES6 en ES5, Sass ou Less pour compiler du CSS, et d'autres loaders pour gérer des fichiers spécifiques comme les images ou les polices. Plugins : Webpack a un système de plugins puissant qui peut être utilisé pour étendre ses fonctionnalités. Les plugins peuvent accomplir une variété de tâches comme l'optimisation des fichiers, la gestion des assets, la définition de variables d'environnement, etc.
Angular Vs React
Angular Angular est un framework complet, Il est orienté pour les applications SPA (Single Page Application).
Avantages :
Framework complet : Angular fournit une solution complète avec des outils intégrés comme le système de routage, le binding bidirectionnel des données, les services, les formulaires réactifs, etc.
Opinionné : Angular suit une architecture stricte et guide les développeurs à travers des bonnes pratiques standardisées . TypeScript : Angular est conçu en TypeScript, ce qui apporte une meilleure gestion des erreurs, une complétion de code améliorée, et une meilleure maintenabilité pour les projets de grande échelle. Structure modulaire : Angular facilite la création de composants modulaires, réutilisables, et testables.
Inconvénients : Courbe d'apprentissage : Angular peut sembler complexe au début, surtout avec la nécessité de comprendre TypeScript, la syntaxe des décorateurs, et les concepts comme les modules et les injecteurs de dépendance. Performance : Parfois, Angular peut être plus lourd pour des applications légères en comparaison avec React. Verbosité : Le code dans Angular peut être verbeux, nécessitant plusieurs fichiers pour des composants simples.
ReactJS React est une bibliothèque JavaScript,Il est utilisé pour la création d'interfaces utilisateur (UI) avec une approche basée sur les composants.
Avantages : Flexibilité : React est une bibliothèque légère et flexible. Il ne dicte pas comment structurer une application, permettant aux développeurs de choisir les outils (par ex., gestion des états avec Redux, React Router pour le routage).
JSX : React utilise JSX, qui combine JavaScript et HTML dans le même fichier, ce qui rend l'écriture des composants plus intuitive.
Performances : La gestion optimisée du DOM via le "Virtual DOM" permet des mises à jour rapides et efficaces de l'interface, ce qui se traduit souvent par de meilleures performances sur des applications légères.
Inconvénients : Pas de structure imposée : La flexibilité de React peut être un inconvénient pour les grandes équipes ou projets, car elle peut entraîner des incohérences dans l'architecture de l'application.
Écosystème fragmenté : Contrairement à Angular qui a tout intégré, avec React il faut choisir ses propres outils (gestion d'état, routage, etc.), ce qui peut être déroutant pour les débutants. JSX : Si JSX est apprécié par certains, d'autres trouvent que mélanger HTML et JavaScript peut nuire à la lisibilité.
e.preventDefault
e.preventDefault() est une méthode utilisée en JavaScript pour empêcher le comportement par défaut d'un événement. En React, la raison d'utiliser e.preventDefault() est de garder le contrôle sur la logique des événements dans une application.
Dans React, l'objet e dans e.preventDefault() fait référence à un SyntheticEvent, qui est une abstraction des événements du DOM natifs. Ce système d'événements garantit une compatibilité inter-navigateurs et offre les mêmes propriétés et méthodes que les événements natifs (comme preventDefault(), stopPropagation(), etc.).
React 19
- Nouveau compilateur React
React 19 intègre un nouveau compilateur qui optimise automatiquement les re-rendus des composants. C'est plus nécessaire d'ajouter manuellement des hooks tels que useMemo, useCallback et React.memo, facilitant ainsi la gestion des performances.
- Actions
Les Actions simplifient la gestion des mutations de données et des soumissions de formulaires. Elles automatisent la gestion des états pendants, des erreurs, des mises à jour optimistes et des requêtes séquentielles, réduisant ainsi le code boilerplate nécessaire pour ces opérations.
- Composants Serveur (Server Components) et Actions Serveur
Les Composants Serveur permettent de rendre des composants côté serveur, améliorant les performances et le référencement SEO. Les Actions Serveur offrent la possibilité aux composants clients d'appeler des fonctions asynchrones exécutées sur le serveur, simplifiant ainsi la gestion des opérations côté serveur.
- Nouveaux hooks
React 19 introduit plusieurs nouveaux hooks :
use(): permet de lire des ressources asynchrones directement dans le rendu, suspendant le rendu jusqu'à la résolution de la promesse.
useFormStatus(): offre un accès à l'état d'un formulaire parent, utile pour gérer les états de soumission et les erreurs sans avoir à propager manuellement les props.
useActionState(): facilite la gestion des états pendants et des erreurs lors de l'exécution d'actions asynchrones.
useOptimistic(): aide à gérer les mises à jour optimistes de l'interface utilisateur pendant les mutations de données asynchrones, offrant une meilleure expérience utilisateur
Activity
ViewTransition
addTransitionType
Atomic design
Les concepts Atom, Molecule, Organism, Template et Page proviennent de la méthodologie Atomic Design, créée par Brad Frost. Cette approche est utilisée dans les design systems pour organiser et structurer les composants d'une interface utilisateur en niveaux logiques, afin de faciliter leur réutilisation et leur gestion.
Atom: Les atoms (ou atomes) sont les éléments indivisibles d'une interface utilisateur. Ce sont des composants de base qui ne peuvent pas être décomposés davantage.
Exemples : Un bouton (\<button>), Un champ de texte (\<input>), Une icĂ´ne
Utilité : Ils servent de blocs de construction pour tous les autres composants.
Molecule: Une molecule (ou molécule) est une combinaison de plusieurs atoms qui travaillent ensemble pour former une unité fonctionnelle simple. Les molécules introduisent déjà une certaine logique ou interactivité.
Exemples : Une barre de recherche : composée d'un champ de texte (\<input>) et d'un bouton (\<button>). Un tag avec une icône : une icône (\<svg>) et un texte stylisé.
Utilité : Les molécules créent des composants simples mais significatifs, qui peuvent être réutilisés à différents endroits.
Organism: Un organism (ou organisme) est une combinaison de molecules (et parfois d'atoms) qui fonctionnent ensemble pour créer des sections complexes de l'interface.
Exemples :Un en-tête (header) : peut inclure un logo (molecule), une barre de navigation (molecule), et un champ de recherche (molecule). Une carte produit dans un e-commerce : composée d'une image, d'un titre, d'un prix et d'un bouton d'achat.
Utilité : Les organismes représentent des blocs fonctionnels de haut niveau dans votre design system. Ils permettent de construire des sections complètes de pages.
Template: template est une structure globale ou un agencement qui combine plusieurs organismes et les place dans un cadre spécifique pour créer la structure d'une page.
Exemples : Une page produit dans un e-commerce : composée d'un en-tête (organisme), d'un carrousel de produits (organisme), et d'un pied de page. Une page d'accueil avec une bannière, une liste d'articles et une section "Contact".
Utilité : Les templates définissent la disposition et l'agencement des composants sans contenir de données finales. Ils sont souvent statiques, servant de squelette ou de maquette.
Page: Une page est une instance concrète d'un template, avec des données réelles ou des contenus spécifiques. Elle représente l'étape finale du design, celle qui est directement visible par l'utilisateur.
Exemples : Une page produit pour un T-shirt spécifique (avec un nom, un prix, une image réelle, etc.). Une page d'accueil avec des articles et images réels provenant d'une base de données.
Utilité : Les pages montrent à quoi ressemble réellement l'interface avec des données concrètes. Elles permettent de valider que les templates, organismes, molécules et atomes fonctionnent correctement ensemble.
Css optimisation
Il a plusieurs technique pour optimiser le css tels que:
Optimisation du poids des fichiers CSS
- Minification : Supprimer tous les espaces, tabulations, commentaires inutiles (cssmin, csso, etc.).
- Compression GZIP ou Brotli :Configurer le serveur pour compresser les fichiers CSS avant de les envoyer au navigateur.Purge du CSS inutile (PurgeCSS, UnCSS) :Retirer toutes les règles CSS qui ne sont jamais utilisées sur le site.
- Concaténation : Combiner plusieurs fichiers CSS en un seul pour réduire le nombre de requêtes HTTP (attention aux stratégies modernes HTTP/2 qui parfois favorisent plusieurs petits fichiers).
Optimisation en architecture CSS
- Méthodologies de structuration :Utiliser BEM (Block-Element-Modifier), OOCSS (Object-Oriented CSS), ou SMACSS pour garder un code maintenable et prévisible.
- Utiliser les préprocesseurs (SASS, LESS) intelligemment : Mais sans créer d'inflation de CSS avec des imbrications (nesting) trop profondes.
- Modulariser le CSS : Dans les projets modernes (React, Vue), utiliser des systèmes de CSS Modules, Styled Components pour éviter les fuites de styles.
Best Practices CSS
- Adopter une méthodologie : Utiliser BEM (Block Element Modifier), OOCSS, SMACSS, ou Atomic Design pour rendre ton CSS clair, modulaire et prévisible.
- Structurer les fichiers CSS : Diviser le CSS en plusieurs fichiers logiques : base/ (reset, typographie, variables), components/ (boutons, cartes, formulaires), layouts/ (grilles, en-tête, pied de page), pages/ (styles spécifiques à une page)
- Limiter la profondeur des sélecteurs : Maximum 2 à 3 niveaux de profondeur.
Mobile First
Le Mobile First est un principe de conception qui recommande de concevoir une interface utilisateur en priorité pour les petits écrans, tels que les smartphones, puis d'adapter et d'étendre aux écrans plus grands, tels que les tablettes et les ordinateurs de bureau. En utilisant le des unités relatives comme %, em(unité de mesure longueur des espaces), ou rem(root em) pour la mise en page et la typographie. ou utilisation Flexbox ou Grid CSS pour créer des grilles qui s'adaptent à différentes tailles d'écran.
Raisons principales d'utiliser le Mobile First :
- La majorité du trafic web est mobile: Aujourd'hui, une grande partie des utilisateurs accède à Internet via leur smartphone. Concevoir d'abord pour mobile garantit une bonne expérience pour la majorité.
- Meilleure performance: Le Mobile First pousse à charger uniquement les éléments essentiels. Cela rend les pages plus rapides, surtout sur des connexions mobiles (3G/4G).
- Simplicité et priorisation du contenu: Les petits écrans obligent à aller à l'essentiel. Cela aide à mieux hiérarchiser l'information, ce qui profite aussi aux versions desktop.
Pixel perfect
Pixel perfect, ça veut dire que l'interface développée correspond exactement au design fourni, au pixel près.mêmes espacements, mêmes tailles de police, mêmes couleurs, mêmes alignement.
L'UI est fidèle à la maquette.
Je m'assure du pixel perfect avec: précision dès le développement, vérification visuelle avec Design on fait review design, et outils adaptés.
Use client
Cette directive est utilisée pour indiquer que certains composants ou parties du code doivent être exécutés côté client uniquement. Elle permet de s'assurer que certains comportements interactifs, dépendants du navigateur ou des APIs web spécifiques au client, sont traités au bon endroit.
Avantages :
- Gestion de l'état et des effets (hooks React) : use client permet l'utilisation de hooks comme useState ou useEffect, qui ne peuvent pas fonctionner côté serveur. Cela est essentiel pour gérer des interactions et des mises à jour d'UI basées sur des événements utilisateur.
- Interopérabilité avec des bibliothèques du client : Certaines bibliothèques (comme des animations ou des graphiques interactifs) nécessitent d'être exécutées côté client, car elles dépendent du DOM ou d'éléments spécifiques au navigateur.
- Optimisation du rendu : Avec use client, ces composants seront chargés seulement au moment nécessaire, réduisant la charge initiale du serveur.
Use server
Cette directive est au cœur de la stratégie de rendu côté serveur (SSR) dans Next.js. Elle permet de spécifier que certains composants ou morceaux de logique sont exclusivement exécutés côté serveur.
Avantages :
- Accès aux données côté serveur : use server est utile pour récupérer des données sensibles ou spécifiques au serveur (comme une base de données ou des API sécurisées). Cela permet de sécuriser la logique métier ou la gestion des données.
- Optimisation des performances : En séparant les composants qui peuvent être rendus côté serveur, on peut diminuer la quantité de JavaScript envoyée au client, réduisant ainsi le temps de chargement initial et améliorant l'expérience utilisateur.
- Simplification du code côté serveur : Au lieu d'avoir à gérer manuellement ce qui doit être rendu côté client ou serveur, la directive use server permet d'indiquer explicitement que ce code ne sera jamais envoyé au client. Cela clarifie les responsabilités entre les deux côtés de l'application.
Challenge optimisation
Dans ma mission précédente, je travaillais sur une application à fort trafic qui devait être rapide et fluide, Comme on a des composants visuels lourds comme des animations et des graphiques interactifs. La complexité augmentait avec l'utilisation de plusieurs librairie et la grande quantité de données à afficher.
Pour résoudre ce problème, j'ai adopté plusieurs approches tels que
L'optimisation du rendu côté client
- Lazy Loading et Code Splitting : J'ai implementé la technique de "lazy loading", les composants n'étaient chargés lorsqu'ils étaient réellement nécessaires, ça reduit la charge initiale. J'ai utilisé le "code splitting" pour diviser les bundles JavaScript en fichiers plus petits et spécifiques, ce qui permettait d'améliorer la performance l'application
- Mémoïsation avec React (useMemo, useCallback) : pour éviter des rendus inutiles, lors de l'interaction avec des composants réactifs.
Optimisation de la gestion de l'état global (Redux)
Pour l'application Mynexity, on a auparavant un state global qui contient beaucoup de données partagées entre différents composants. Pour réduire l'encombrement du store et éviter des rerendering inutiles, j'ai mis en place plusieurs optimisations :
- Localisation de l'état : J'ai analysé les données pour déterminer lesquelles devaient réellement être partagées globalement. Lorsque possible, j'ai mis comme state lau niveau des composants pour alléger le state global.
- Caching et Sélecteurs (Reselect et Cache Invalidation) : J'ai utilisé des sélecteurs mémoïsés via Reselect pour éviter de recalculer des sélecteurs lorsque les données n'avaient pas changé. Et l'ulisation d'invalidation de cache pour maintenir le state à jour sans affecter les performances.
Analyse des performances : J'ai utilisé des outils comme Lighthouse et Chrome DevTools pour identifier les goulets d'étranglement au niveau des temps de chargement, et j'ai optimisé les assets (minification, compression des images, etc.) et réduit le nombre de requêtes réseau.
Collaboration inter-équipe : Pour bien structure bien les données j'ai travaillé avec les développeurs back-end pour améliorer les APIs et limiter les appels redondants et de mieux paginer les données envoyées au front.
Refactoring de code: L'un des aspects les plus délicats dans une mission que j'ai réalisée a été la refactorisation de code sans tests, avec une structure de code mal organisée. En, j'ai adopté une approche progressive tels que la mise en place de:
- Tests Snapshots : J'ai choisi des tests de snapshot pour m'assurer que les modifications dans les composants n'affectaient pas de manière imprévue le rendu visuel ou fonctionnel. Ça me permet de faire la refacto et d'assurer que mes modifications ne provoquent pas de régressions.
- Mise en place de tests unitaires et d'intégration : En plus des snapshots, j'ai mis en place des tests unitaires et d'intégration au fur et à mesure sur les parties critiques du code.Celà permis d'améliorer la couverture de tests, et avoir aussi de créer une base solide
Throttling Vs debouncing
- Throttling : limite l'exécution d'une fonction à un appel toutes les X ms.
- Debouncing : attend une période d'inactivité pour exécuter la fonction.
Utilisation :
- Throttle : scroll, resize events.
- Debounce : input search, autocomplete.
Feature fiere
Le feature dont je suis le plus fier, c'est le développement fullstack du module de rendez-vous pour la téléconsultation. J'ai géré à la fois le frontend avec Next.js et Material UI, et le backend en NestJS avec Postgres. Le module couvrait la sélection de créneaux en temps réel, la synchronisation avec les calendriers des médecins, le paiement via Stripe, l'envoi de notifications et la sécurisation par OTP.
Côté complexité, le premier défi majeur a été la gestion des conflits de réservation. Pour éviter que deux patients réservent le même créneau simultanément, j'ai mis en place une vérification serveur qui contrôle la disponibilité du créneau en base. En cas de conflit, l'API rejette la demande avec une erreur claire. Pour fiabiliser ça en cas d'accès concurrent, j'ai encapsulé la logique dans une transaction SQL avec un niveau d'isolation SERIALIZABLE, ce qui garantit qu'aucun double booking ne peut se produire. En complément, on a ajouté un verrouillage temporaire des créneaux pendant le paiement pour améliorer l'expérience utilisateur.
Le second défi a été la gestion des fuseaux horaires entre patients et médecins. J'ai normalisé toutes les dates au format UTC côté backend et base de données, puis le frontend convertit dynamiquement ces dates en heure locale via le fuseau horaire du navigateur. Ça permet une gestion fiable, cohérente, et sans bug, même en cas de changement d'heure ou si le médecin et le patient sont dans des pays différents."
Accessibilité
Objectif : rendre le web utilisable par tous, y compris les personnes en situation de handicap.
Bonnes pratiques :
- Utiliser les balises HTML sémantiques (\<nav>, \<header>, \<main>, etc.).
- Gérer correctement le focus clavier (ex. : avec tabindex, aria-*).
- Fournir des alternatives textuelles (alt sur les images, aria-label).
- S'assurer que les contrastes de couleurs sont suffisants.
- Tester avec des lecteurs d'écran (NVDA, VoiceOver).
Mon approche sur l'accessibilité
Je travaille sur trois axes :
- sémantique : structure HTML correcte, rôles natifs privilégiés
- interaction : navigation clavier, focus management, pièges à focus maîtrisés
- perception : contrastes, feedback, libellés, erreurs compréhensibles
Je cherche à rendre les composants accessibles par défaut, au niveau du design system, pour éviter de redécouvrir les mêmes problèmes feature par feature.
J'ai travaillé sur l'accessibilité de l'application pour assurer qu'elle soit utilisable par tous les utilisateurs, y compris ceux utilisant des technologies d'assistance.
Concrètement, j'ai :
- ajouté des attributs ARIA pour améliorer la compréhension des composants interactifs
- vérifié la navigation au clavier (tab, focus visible, ordre logique)
- amélioré les contrastes de couleurs pour respecter les standards WCAG
- utilisé des balises HTML sémantiques (header, nav, main, button…)
- ajouté des labels et descriptions pour les formulaires
- testé avec des lecteurs d'écran pour valider l'expérience
L'objectif était de rendre l'interface plus inclusive et conforme aux bonnes pratiques d'accessibilité.
Outils :
- Lighthouse (audit accessibilité)
- axe DevTools
- Testing Library avec toBeAccessible() (via jest-axe)
Défis techniques rencontrés & solutions
- Composants personnalisés (modales, dropdowns, autocomplétion)
Problème : Les composants custom n'ont pas de comportement natif clavier ou lecteur d'écran.
Solution : Suivre les [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/) pour le rôle, le focus, les touches (ESC, flèches). Exemple : pour une modale, ajouter : role="dialog" aria-modal="true" focus piégé à l'intérieur ESC pour fermer
- Changement de page sans rechargement (SPA/Next.js)
Problème: Le lecteur d'écran ne perçoit pas qu'une nouvelle page est chargée.
Solution: Utiliser un aria-live region pour annoncer le changement de contenu. Gérer le focus à chaque navigation (focus main content). document.getElementById('main-content')?.focus();
- Internationalisation & accessibilité
Problème : Certains attributs (aria-label, title) sont codés en dur → problèmes multilingues.
Solution : Utiliser i18n aussi pour les attributs ARIA :
\<button aria-label={t('accessibility.openMenu')}>{t('menu')} \</button>
- Gestion des focus dans les composants dynamiques
Problème : Sur le projet BNP Paribas, certaines modales et dropdowns étaient créés dynamiquement. Lors de l'ouverture, le focus ne se déplaçait pas correctement → les utilisateurs clavier perdaient la navigation.
Solution : J'ai mis en place un focus trap (soit avec focus-trap-react, soit en le codant manuellement) pour limiter la navigation clavier Ă la modale ouverte, et restaurer le focus Ă la fermeture.
Difficulté : Il fallait gérer les cas où plusieurs modales ou overlays pouvaient être ouverts en cascade.
- Accessibilité des composants custom (UI non natifs)
Problème : on utilisait des composants Material UI et certains étaient surchargés pour le design → perte de sémantique (ex. un \<div> faisait office de bouton).
Solution : J'ai veillé à ce que ces composants custom : soient cliquables et accessibles au clavier (onKeyDown + tabIndex=0), aient un rôle correct (role="button") et un aria-pressed ou aria-expanded si nécessaire.
Difficulté : Éviter de casser le style tout en gardant la logique d'accessibilité intacte.
- Composants dynamiques et annonces pour lecteurs d'écran
Problème : Certaines notifications (success/error) n'étaient pas annoncées par les lecteurs d'écran.
Solution : J'ai ajouté des régions aria-live (aria-live="assertive") pour forcer les lecteurs d'écran à annoncer les changements de statut.
Difficulté : Éviter les annonces en double quand plusieurs événements se déclenchaient simultanément.
Version plus poussée
L'accessibilité ne se limite pas à respecter quelques règles techniques, c'est un vrai travail d'équipe et un processus continu.
Sur mes projets, j'essaie d'aller plus loin :
- Intégration dans le design system : avec Storybook, on a documenté les composants accessibles (boutons, formulaires, modales) afin que toute l'équipe puisse les réutiliser sans recréer de dettes techniques.
- Collaboration avec l'UX/UI : dès la conception, je participe aux discussions pour m'assurer que les maquettes respectent les contrastes, la hiérarchie visuelle et l'ergonomie clavier.
- Revues de code focalisées sur l'accessibilité : pendant les code reviews, je vérifie les labels, le focus, les rôles ARIA, et je propose des améliorations si besoin.
- Tests automatiques : j'intègre des outils comme jest-axe ou les add-ons Storybook accessibility pour détecter automatiquement les problèmes avant la mise en production.
- Sensibilisation de l'équipe : je partage régulièrement des bonnes pratiques et des retours d'expérience pour que l'accessibilité devienne un réflexe collectif.
Sécurité
Objectif : éviter les vulnérabilités côté client.
Risques communs en front-end :
- XSS (Cross-Site Scripting) : éviter d'injecter du HTML via innerHTML sans sanitation.
- CSRF : bien que souvent géré côté serveur, être conscient des requêtes sensibles.
- Exposition de données sensibles dans le code client : ne jamais embarquer de secrets/API keys non publiques.
Bonnes pratiques :
- Utiliser un CSP (Content Security Policy).
- Éviter les dépendances non maintenues ou malveillantes (vérifier avec npm audit).
- Échapper/sanitizer toutes les entrées utilisateurs.
Comportement navigateur lorsqu'un utilisateur tape XXX dans la barre d'adresse de son navigateur et appuie sur Entrée
1. Résolution DNS (Domain Name System): Le navigateur demande : « Quelle est l'adresse IP de xxxx.com ? » Il consulte d'abord son cache DNS local. Sinon, il demande à un serveur DNS (souvent celui du FAI ou de Google/Cloudflare). Résultat : il reçoit une adresse IP, ex. 192.0.2.1.
2. Connexion TCP + Sécurisation via HTTPS (TLS/SSL): Le navigateur ouvre une connexion TCP avec le serveur IP. Ensuite, il effectue une négociation TLS (si HTTPS) pour établir une connexion sécurisée. Certificat SSL est vérifié ici :
Est-il valide ? ou Expiré ? et Correspond-il bien à l'adresse XXX.fr ?
En front : → Si le certificat est invalide, le navigateur bloque l'accès avant même de charger le HTML.
3. Envoi de la requête HTTP Une fois connecté, le navigateur envoie une requête HTTP
4. Réponse du serveur
Le serveur retourne les contenues. Le navigateur commence à parser le HTML dès les premiers octets reçus.
5. Parsing et rendu HTML + ressources
Le navigateur commence à construire le DOM (Document Object Model). Il repère ensuite : Les feuilles de style CSS → Téléchargées et appliquées. Les scripts JavaScript → Exécutés (sauf si defer ou async). Les images, polices, iframes, etc.
En front : → Un JS bloquant (\<script> sans defer) peut bloquer le rendu. → Mauvais chargement des polices \= problème UX. → meta tags impactent SEO et accessibilité (lang, viewport, etc.).
6. Hydratation (si React/Next.js)
Si c'est un site en React SSR (comme Next.js) : Le HTML est d'abord rendu côté serveur. Ensuite, React hydrate ce contenu côté client : il attache les événements, active les composants interactifs.
Test composant
En React, je distingue trois types principaux de tests :
1. Tests unitaires : je teste des composants ou fonctions isolés. J'utilise généralement Jest avec React Testing Library. Par exemple, je peux tester qu'un bouton affiche bien un texte ou qu'une fonction utilitaire retourne le bon résultat.
2. Tests d'intégration : je vérifie que plusieurs composants fonctionnent bien ensemble. Par exemple, je teste qu'un formulaire affiche une erreur quand on soumet un champ vide. J'utilise aussi React Testing Library ici, car elle simule bien l'interaction utilisateur.
3. Tests end-to-end (E2E) : je simule le comportement de l'utilisateur dans le navigateur. Pour ça, j'utilise Cypress (ou parfois Playwright). Je teste le parcours complet : par exemple, un utilisateur qui se connecte, ajoute un produit au panier, puis valide la commande.
Comment on fait le test composant
Quand je teste un composant React, je privilégie les tests d'intégration, même si parfois je fais aussi des tests unitaires.
En fait, avec React Testing Library, on est encouragé à tester le composant comme un utilisateur l'utiliserait, donc en simulant les interactions (clic, saisie, etc.), ce qui rend le test plus proche de la réalité. C'est plus un test d'intégration qu'unitaire.
Exemple : si j'ai un composant LoginForm avec deux champs et un bouton, je ne vais pas tester chaque champ individuellement (test unitaire), mais plutôt vérifier que l'ensemble fonctionne bien : l'utilisateur remplit les champs, clique sur "Se connecter", et je vérifie que l'action correcte est déclenchée.
J'utilise Jest + React Testing Library pour ça. Je peux mocker les fonctions externes (comme les appels API ou les hooks custom) si besoin.
J'écris des tests unitaires seulement quand j'ai une logique isolée, par exemple une fonction utilitaire ou un hook personnalisé.
Best Practices de Sécurité
- Éviter les failles XSS (Cross-Site Scripting)
React protège par défaut contre le XSS, mais tu peux encore te piéger si tu désactives cette protection.
Bonnes pratiques :
- Ne jamais utiliser dangerouslySetInnerHTML sauf cas ultra-contrôlé.
- Ne rends jamais du HTML dynamique non filtré (par exemple depuis l'utilisateur).
- Si tu dois afficher du HTML : utilise une lib de "sanitization" comme [DOMPurify](https://github.com/cure53/DOMPurify).
- Stockage sécurisé des tokens (authentification)
Les tokens JWT ou autres ne doivent jamais être stockés dans localStorage ou sessionStorage pour des apps sensibles.
Meilleure approche :
Stocke le token dans un cookie HTTP-only, configuré avec : - HttpOnly: true - Secure: true - SameSite: Strict - Cela empêche tout accès via JavaScript → protection contre le XSS.
- Sécuriser les appels API
Bonnes pratiques :
- Utilise HTTPS uniquement
- Ne stocke pas d'info sensible côté client
- Ne laisse pas les endpoints exposés sans vérification côté backend
- Implémente rate limiting et authentification forte (JWT, OAuth, etc.)
Content-Security-Policy (CSP)
La Content-Security-Policy (CSP) est un en-tête de sécurité HTTP qui permet au serveur de contrôler les sources de contenu qu'un navigateur est autorisé à charger pour une page web. But principal : Empêcher les attaques XSS, les injections de scripts et le chargement de contenu malveillant.
Attaque XSSF ou CRSF
XSS (Cross-Site Scripting) : Une attaque XSS permet à un attaquant d'injecter du code JavaScript malveillant dans des pages web consultées par d'autres utilisateurs.
CSRF (Cross-Site Request Forgery) : Une attaque CSRF consiste à induire un utilisateur légitime à exécuter des actions non désirées sur un site, il est authentifié, sans son consentement.
Côté Front-End (Client)
Échapper les Entrées Utilisateur
- Utilisez des techniques comme l'échappement HTML pour désactiver le code JavaScript potentiellement malveillant avant d'afficher du contenu utilisateur. Par exemple, en utilisant des bibliothèques comme DOMPurify pour nettoyer les entrées.
Validation Côté Client
- Validez et filtrez les données côté client pour détecter les scripts malveillants ou les caractères non autorisés avant de les soumettre au serveur.
Headers de Sécurité
- Utilisez des en-têtes HTTP comme Content-Security-Policy (CSP) pour restreindre les sources de contenu autorisées (comme les scripts et les styles) et réduire les risques d'exécution de scripts malveillants.
Utilisation de Cookies Sécurisés
- Utilisez l'attribut SameSite pour les cookies afin de limiter les attaques CSRF en empĂŞchant les navigateurs de renvoyer automatiquement les cookies lors des requĂŞtes cross-site.
function currying
Le currying est une technique qui transforme une fonction à plusieurs arguments en une chaîne de fonctions, chacune prenant un seul argument (ou un sous-ensemble d'arguments).
Pourquoi ça apparaît en React
- a) Passage de paramètres aux handlers
- En React, quand on veut donner des paramètres à un onClick ou autre event handler, on peut utiliser une fonction curryfiée pour éviter les .bind ou les fonctions anonymes lourdes.
- b) Partage de logique entre composants
- Avec le currying, on peut créer des fonctions réutilisables qui capturent un contexte et renvoient une fonction adaptée.
Avantages en React
- Clarté : chaque fonction ne gère qu'une seule "responsabilité" (capturer un paramètre, ou gérer l'event).
- Réutilisabilité : tu peux préconfigurer une fonction pour différents composants.
- Évite bind : pas besoin de .bind(this, arg) ou de recréer des fonctions anonymes en JSX.
TanStack query
TanStack Query c'est une librairie qui permet de simplifier la gestion des données côté client car il nous gèrele cache, le refetch, les états de chargement/erreur et même l'invalidation après mutation. Résultat : moins de code useEffect/useState, des données toujours fraîches, et une meilleure UX grâce au cache et au background refresh.
Ce qu'apporte TanStack Query :
- Cache & synchronisation automatique: Stocke les réponses API par queryKey, réutilise les données quand on revient sur une page. et Évite les requêtes inutiles (deduplication).
- Mise à jour en arrière-plan (stale-while-revalidate): Affiche les données du cache immédiatement, puis refetch en arrière-plan pour rafraîchir. UX plus fluide (pas d'écran vide à chaque navigation).
- Gestion des états intégrée: isLoading, isError, isFetching, isStale → plus besoin de les coder à la main.
- Invalidation ciblée: Après une mutation (POST/PUT/DELETE), on peut invalider précisément les queries impactées → données toujours cohérentes.
staleTime définit combien de temps une donnée est considérée fraîche avant d'être marquée comme "stale" et donc potentiellement refetchée.
exemple: staleTime: 10_000 → si on revient sur la page dans les 10s, les données s'affichent directement sans refetch.
gcTime définit combien de temps la donnée reste en mémoire après qu'il n'y a plus d'abonnés (composants montés) avant d'être supprimée du cache.
exemple: gcTime: 5 * 60_000 → les données restent 5 min en mémoire même si on change de page.
WAF
WAF (Web Application Firewall) : Un pare-feu applicatif web (WAF) est un dispositif de sécurité (logiciel ou matériel) placé devant une application web pour filtrer, surveiller et bloquer le trafic HTTP malveillant.
Rôle : Il protège les applications web contre les attaques courantes comme :
- Injection SQL
- Cross-Site Scripting (XSS)
- Cross-Site Request Forgery (CSRF)
- Exploitation de vulnérabilités connues
Fonctionnement : Le WAF analyse les requêtes HTTP/HTTPS entrantes et sortantes selon des règles de sécurité (signatures, comportement, listes noires/blanches).
OWASP (Open Web Application Security Project)
L'OWASP est une organisation internationale à but non lucratif qui œuvre pour améliorer la sécurité des applications web.
RĂ´le principal :
- Publier des guides, outils et ressources pour les développeurs et les entreprises.
- Le plus connu est le OWASP Top 10, une liste des 10 principales failles de sécurité web (mise à jour régulièrement).
Exemples de failles OWASP Top 10 :
- A01: Injection
- A02: Mauvaise gestion de l'authentification A03: Exposition de données sensibles
- A05: Mauvaise configuration de sécurité
- A04: Insecure Design (Conception non sécurisée) : Exemple : Une application de e-commerce qui ne limite pas le nombre de tentatives de paiement, permettant des attaques par force brute.
- A05: Security Misconfiguration (Mauvaise configuration de sécurité) Exemple : Un serveur web expose les pages d'administration par défaut (/phpmyadmin) sans être protégées.
- A06: Vulnerable and Outdated Components (Composants vulnérables ou obsolètes): Exemple : Utiliser une ancienne version de Struts ou WordPress avec des failles connues et non corrigées.
- A07: Identification and Authentication Failures (Défaillances d'authentification): Exemple : Mots de passe faibles acceptés (123456) ou absence de double authentification (MFA).
- A08: Software and Data Integrity Failures (Défaillances d'intégrité logicielle et des données) Exemple : Téléchargement automatique d'une mise à jour sans vérifier la signature → possibilité d'injecter un malware.
- A09: Security Logging and Monitoring Failures (Défaillances de journalisation et de surveillance): Exemple : Aucune alerte n'est générée après 1000 tentatives de connexion échouées → attaque par brute force indétectée.
- A10: Server-Side Request Forgery (SSRF – falsification de requêtes côté serveur): Exemple : Une application permet de télécharger une image depuis une URL fournie par l'utilisateur, mais sans validation → un attaquant peut accéder à http://localhost:8080/admin.
Http
HTTP (HyperText Transfer Protocol) est un protocole de communication utilisé pour échanger des informations sur le web. C'est le protocole, permettant à un client (comme un navigateur web) de demander des ressources à un serveur (comme une page web, une image ou une API).
Comment fonctionne HTTP ?
HTTP suit un modèle requête-réponse où :
Le client (exemple : un navigateur web ou une application) envoie une requĂŞte HTTP au serveur.
Le serveur traite la requête et envoie une réponse HTTP.
RequĂŞte HTTP :
La requĂŞte contient plusieurs parties :
- Méthode HTTP : Indique l'action demandée. Exemples :
GET : Récupérer une ressource (comme une page ou une image).
POST : Envoyer des données au serveur (comme un formulaire ou une API).
PUT : Mettre Ă jour ou remplacer une ressource.
DELETE : Supprimer une ressource.
- URL (Uniform Resource Locator) : Spécifie la ressource demandée.
- En-têtes (Headers) : Métadonnées sur la requête (type de contenu, authentification, etc.).
- Corps (Body) : Contenu de la requête, utilisé surtout avec POST ou PUT.
Https
HTTPS (HyperText Transfer Protocol Secure) est une version sécurisée du protocole HTTP. Il ajoute une couche de chiffrement et d'authentification grâce au protocole SSL/TLS (Secure Sockets Layer/Transport Layer Security), garantissant que les données échangées entre le client (navigateur) et le serveur restent confidentielles et intègres.
Comment HTTPS fonctionne ?
HTTPS combine le fonctionnement de HTTP avec une couche de sécurité par SSL/TLS.
Le client et le serveur établissent une connexion sécurisée et le certificat SSL/TLS est échangé pour authentifier le serveur.
Une clé de session (clé symétrique) est générée et utilisée pour chiffrer les données échangées.:
Toutes les communications HTTP normales (requêtes et réponses) se font à travers cette connexion sécurisée.
Http 1 VS 2
HTTP 1
- Les requêtes et réponses sont envoyées une à la fois sur une connexion TCP.
- Pour charger plusieurs ressources simultanément, il est nécessaire d'ouvrir plusieurs connexions parallèles (souvent limitées à 6 connexions par domaine dans les navigateurs).
- Cela peut entraîner une surcharge réseau et un ralentissement.
HTTP 2
- Permet le multiplexage, c'est-à -dire plusieurs requêtes et réponses envoyées simultanément sur une seule connexion TCP.
- Les ressources sont chargées plus rapidement sans nécessité d'ouvrir plusieurs connexions.
HTTP/1.1 :
- Les en-têtes HTTP sont envoyés en texte brut à chaque requête.
- Les mêmes en-têtes sont souvent répétés pour plusieurs requêtes (comme les cookies, les User-Agent, etc.), ce qui augmente inutilement la taille des données.
HTTP/2 :
- Utilise le protocole HPACK pour compresser les en-tĂŞtes.
- Les en-têtes redondants ne sont pas retransmis, réduisant ainsi la surcharge.
Certificat SSL/TLS ?
Un certificat SSL/TLS est un fichier électronique émis par une autorité de certification (CA, Certificate Authority).
Il contient :L'identité du propriétaire (nom de domaine, organisation, etc.).Une clé publique pour établir une connexion sécurisée.Une signature numérique de l'autorité de certification.
Fonctionnement :
Lorsqu'un client (navigateur) se connecte à un site HTTPS, il demande le certificat SSL/TLS.Le certificat est vérifié par le navigateur pour s'assurer qu'il est valide et qu'il provient d'une autorité de confiance.Une connexion sécurisée est établie si tout est en ordre.
CORS
CORS ou (Cross-Origin Resource Sharing) est un mécanisme de sécurité qui permet aux serveurs de contrôler les requêtes provenant de domaines externes. CORS peut être configuré avec le middleware cors pour Express, en spécifiant les domaines autorisés, les méthodes, et les en-têtes. Cela protège contre les requêtes non autorisées provenant d'autres origines.
Il protège les utilisateurs contre les attaques malveillantes comme le Cross-Site Request Forgery (CSRF).
JWT
JWT(JSON WEB TOKEN) est composé de trois parties séparées par des points (.) : header, payload et la signature. Chaque partie est encodée en Base64 pour former un jeton compact.
En-tête (Header) :Contient des métadonnées sur le type de jeton et l'algorithme de signature utilisé pour le sécuriser.
Payload (Charge Utile) : Contient les données réclamées (claims) que le JWT transporte. Il existe trois types de claims(réclamations) : réservées, publiques et privées
Signature : Utilisée pour vérifier que le JWT n'a pas été modifié ou falsifié pendant son transit entre les parties. La signature est calculée à l'aide d'un algorithme headers (par exemple, HMAC SHA-256 ou RSA)
Protection de JWT
Chiffrement des Réclamations :
- Pour protéger les données sensibles, les réclamations peuvent être chiffrées avant d'être ajoutées au JWT. Cela assure leur confidentialité même si le JWT est décodé par des parties non autorisées.
Utilisation de Clés Secrètes :
- Pour les JWT signés (non chiffrés), une clé secrète partagée est utilisée pour générer et vérifier la signature. Cette clé doit être gardée confidentielle pour empêcher la falsification des JWT.
Expiration et Renouvellement :
- Les JWT peuvent inclure une date d'expiration (exp) pour limiter leur durée de validité. Après expiration, ils ne sont plus valides et doivent être renouvelés en générant un nouveau JWT.
Validation Côté Serveur :
- Lorsque le serveur reçoit un JWT, il vérifie la signature pour s'assurer que le JWT est authentique et n'a pas été modifié. Il vérifie également les réclamations pour décider de la suite des actions.
Utilisation de JWT
Authentification et Autorisation :
- JWT est utilisé pour l'authentification des utilisateurs après la connexion initiale. Une fois authentifiés, les utilisateurs peuvent présenter le JWT comme preuve de leur identité pour accéder aux ressources protégées.
APIs et Services Web :
- JWT est largement utilisé dans les APIs et les services web où il est utilisé comme mécanisme de jeton d'accès sécurisé pour contrôler l'accès aux ressources et aux fonctionnalités.
Flex Vs Grid
Flexbox(container et Flex items)
Flexbox est un modèle de disposition unidimensionnelle. C'est-à -dire qu'il peut gérer une seule dimension à la fois : soit en colonne soit en ligne. Ce modèle va permettre de distribuer l'espace entre des objets d'une interface ainsi que de les aligner.
CSS Grid layout
Le module CSS Grid layout (modèle de disposition en grille) qui permet la manipulation d'éléments dans une grille à deux dimensions. Les grilles peuvent être utilisées pour agencer des pages entières ou de petits éléments d'interface.
Contrairement à Flexbox, la grille n'a pas de structure de contenu. Les éléments « enfants » d'un conteneur en grille peuvent être positionnés afin qu'ils se chevauchent ou qu'ils se comportent comme des éléments positionnés.