🧩 Anatomie d'un composant React

Un composant React est une fonction JavaScript qui reçoit des props en entrée et retourne du JSX. C'est la brique de base de toute interface React.

// Structure d'un composant
function NomComposant(props) {
  // 1. Logique / calculs
  const valeur = props.donnee * 2;

  // 2. Gestionnaires d'événements
  function handleClick() {
    console.log('clic !');
  }

  // 3. JSX retourné
  return (
    <div className="composant">
      <h2>{valeur}</h2>
      <button onClick={handleClick}>Cliquer</button>
    </div>
  );
}
✅ Convention : nom en PascalCase (ex : MonComposant), fichier en MonComposant.jsx.

📦 Les props — passer des données

Les props (properties) sont les paramètres d'un composant. Elles sont en lecture seule — un composant ne peut jamais modifier ses propres props.

// Composant parent : passe des props
function App() {
  return (
    <div>
      <Bouton texte="Valider" couleur="vert" onClick={handleSubmit} />
      <Bouton texte="Annuler" couleur="rouge" onClick={handleCancel} />
    </div>
  );
}

// Composant enfant : reçoit les props
function Bouton(props) {
  return (
    <button
      style={{ background: props.couleur }}
      onClick={props.onClick}
    >
      {props.texte}
    </button>
  );
}
⚠️ Les props sont immutables — une règle fondamentale de React. Pour modifier une valeur, utilisez useState (module R03).

✂️ Destructuration des props

On destructure généralement les props dans les paramètres de la fonction pour un code plus lisible.

// Sans destructuration
function Carte(props) {
  return <h2>{props.titre}</h2>;
}

// Avec destructuration (recommandé)
function Carte({ titre, description, couleur }) {
  return (
    <div style={{ borderColor: couleur }}>
      <h2>{titre}</h2>
      <p>{description}</p>
    </div>
  );
}

// Avec alias et valeur par défaut
function Carte({ titre: heading = 'Sans titre', description = '' }) {
  return <div><h2>{heading}</h2><p>{description}</p></div>;
}

🎯 Valeurs par défaut des props

Deux façons de définir des valeurs par défaut : dans la destructuration ou avec defaultProps.

// Méthode moderne — valeurs par défaut dans la destructuration
function Avatar({ nom = 'Anonyme', taille = 48, couleur = '#61dafb' }) {
  return (
    <div style={{
      width: taille,
      height: taille,
      borderRadius: '50%',
      background: couleur,
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      fontWeight: 'bold',
      fontSize: taille * 0.4
    }}>
      {nom[0].toUpperCase()}
    </div>
  );
}

// Utilisation
<Avatar />                          {/* A — taille 48, bleu */}
<Avatar nom="Marie" taille={64} />  {/* M — taille 64, bleu */}
<Avatar nom="Bob" couleur="#f85149" />  {/* B — rouge */}

👶 props.children

La prop spéciale children contient tout ce qui est passé entre les balises ouvrante et fermante du composant.

// Composant conteneur
function Panneau({ titre, children }) {
  return (
    <div className="panneau">
      <h3 className="panneau-titre">{titre}</h3>
      <div className="panneau-corps">
        {children}
      </div>
    </div>
  );
}

// Utilisation — le contenu JSX devient children
function App() {
  return (
    <Panneau titre="Mon panneau">
      <p>Ce texte est dans children</p>
      <button>Un bouton aussi</button>
    </Panneau>
  );
}
children permet de créer des composants de mise en page flexibles (cartes, modales, layouts) sans coupling fort.

🔀 Composition de composants

React favorise la composition plutôt que l'héritage : on assemble de petits composants pour en former de plus grands.

// Composants atomiques
function Badge({ label, couleur = '#61dafb' }) {
  return (
    <span style={{ background: couleur, borderRadius: '12px', padding: '0.2rem 0.6rem', fontSize: '0.75rem' }}>
      {label}
    </span>
  );
}

function Avatar({ nom, taille = 40 }) {
  return (
    <div style={{ width: taille, height: taille, borderRadius: '50%', background: '#61dafb', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 'bold' }}>
      {nom[0]}
    </div>
  );
}

// Composant composite : assemble Avatar + Badge
function CarteUtilisateur({ nom, role, badge }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: '1rem', padding: '1rem', border: '1px solid #30363d', borderRadius: '10px' }}>
      <Avatar nom={nom} taille={48} />
      <div>
        <strong>{nom}</strong>
        <div style={{ fontSize: '0.82rem', color: '#8b949e' }}>{role}</div>
        <Badge label={badge} />
      </div>
    </div>
  );
}

// App finale
function App() {
  return (
    <div>
      <CarteUtilisateur nom="Alice" role="Dev Frontend" badge="React" />
      <CarteUtilisateur nom="Bob" role="Dev Backend" badge="Node.js" />
    </div>
  );
}
📝 Exercices R02 ▶ Mini-projet : Card Gallery 🧠 QCM R02 Suivant : useState →