Aller au contenu

Définition et appel de composants React

Rappels

Fonctions vs. classes

Bien qu'il soit toujours possible d'écrire des composants React sous forme de classes, Meta (Facebook) recommande maintenant de ne plus utiliser cette syntaxe, pour des raisons de clarté et d'optimisation interne. Les composants devraient être écrits sous forme de fonctions, et les fonctionnalités manquantes (accès aux attributs et méthodes spéciaux) peuvent être retrouvées à l'aide de fonctions spéciales, les hooks.

Pour que React reconnaisse qu'une fonction implémente un composant, il faut que son nom commence par une majuscule.

Note : Les hooks sont apparus officiellement dans React 16.8, la version actuelle est 18.2. C'est donc une nouveauté récente à l'échelle de l'évolution de cette bibliothèque.

Les hooks sont régis par des règles :

  • ils peuvent être utilisés uniquement au niveau supérieur d'un composant (pas à l'intérieur d'un test ou d'une boucle)
  • ils peuvent être utilisés uniquement dans un composant React (pas dans une fonction ordinaire)

Il est possible de définir ses propres hooks. Par convention, leur nom commence par use.

DOM virtuel

La rapidité de React provient de ce qu'il gère un DOM virtuel, qui n'est synchronisé avec le DOM physique qu'à certains moments bien définis (le composant est alors réaffiché). Le DOM virtuel permet des modifications asynchrones, contrairement au DOM physique.

État : le hook useState

Un composant a un état interne. Quand l'état change, le composant est réaffiché, c'est React qui décide quand cela doit avoir lieu. Dans un composant fonctionnel, l'état n'est pas accessible directement, c'est pourquoi on passe par le hook useState. Le hook renvoie un tableau de deux constantes : * la valeur courante d'une variable d'état * la fonction de mise à jour de cette variable (qui signale également le changement d'état à React).

Il est impossible de modifier directement la valeur, c'est délibéré.

Effets de bord : le hook useEffect

Si un composant doit, par exemple, charger des données externes lors de son initialisation et les stocker dans son état, il n'est pas possible de le faire directement, car cela créerait une boucle infinie (le composant charge les données -> l'état est modifié -> le composant est réaffiché - > il recharge les (mêmes) données -> l'état est modifié -> ...).

On doit utiliser le hook useEffect. Il possède 3 variantes d'utilisation :

  • Exécution avant chaque réaffichage du composant :

L'argument est une fonction () => {...}. Le contenu de la fonction doit être synchrone. Si nécessaire, il peut mettre à jour l'état du composant sans déclencher de boucle infinie.

useEffect(() => {...})
  • Exécution au montage du composant

On ajoute un second argument qui est un tableau vide :

useEffect(() => {...}, [])
  • Exécution quand des variables (variables d'état, typiquement) changent

Le second argument qui est un tableau qui contient la liste des variables à surveiller :

useEffect(() => {...}, [user, timestamp])

Propriétés d'un composant : props

Lors de son appel, un composant peut recevoir des paramètres, qui sont regroupés sous la forme d'un objet unique, généralement appelé props. Cet objet est en lecture seule.

Par exemple, l'appel :

<Composant1 a={1} b="2" c style={{flex: 1}}>

initialise props avec la valeur :

props = {a: 1, b: "2", c: true, d: {flex: 1}} 

Children

Si un composant est appelé sous la forme d'une paire de balises (ouvrante + fermante), alors le contenu des balises est accessible sous l'attribut children :

<Journee>
  <Matin/>
  <Midi/>
  <Soir/>
</Journee>
export function Journee(props) {
  return props.children.map(comp => <section>{comp}</section>)  
}

Note : la nature exacte des données retournées par children (tableau, objet unique, ...) dépend de la façon dont le composant a été appelé (nombre de sous-composants).

Syntaxes utiles

Les possibilités combinées de Javascript et de React permettent une grande variétés de syntaxes, notamment à l'aide de l'opérateur de décomposition (...).

Définition des propriétés d'un composant

  • Pas de propriétés :
export function MonComposant() {
  return <h1>Hello</h1>
}
  • Objet props :
export function MonComposant(props) {
  return <>
   <h1>{props.title}</h1>
   {props.children}
  </>
}
  • Arguments explicites :
export function MonComposant({title, body}) {
  return <>
   <h1>{title}</h1>
   {body}
  </>
}
  • Une partie des arguments explicites :
export function MonComposant({title, subtitle, ...others}) {
  return <>
   <h1>{title}</h1>
   <h2>{subtitle}</h2>
   {others.children}
  </>
}

Appel d'un composant

Voici quelques syntaxes d'appel disponibles :

  • Passage des paramètres sous forme de "pseudo-attributs" HTML :
export function MonComposant(props) {
  return <SousComposant a={1} b="2"/>
}
  • Passage des paramètres sous forme d'un objet :
export function MonComposant(props) {
  const obj = {a: 1, b: "2"}
  return <SousComposant {...obj}/>
}
  • Passage au sous-composant de l'ensemble des propriétés parentes :
export function MonComposant(props) {
  return <SousComposant {...props}/>
}