Props - Passer des données aux composants

Les props (propriétés) permettent de passer des données d'un composant parent à un composant enfant. C'est la base de la communication en React !

Qu'est-ce qu'une prop ?

Une prop est comme un argument de fonction : elle permet de personnaliser un composant.

jsx
// Sans props (statique)
function Greeting() {
  return <h1>Bonjour Alice !</h1>;
}

// Avec props (dynamique)
function Greeting(props) {
  return <h1>Bonjour {props.name} !</h1>;
}

// Utilisation
<Greeting name="Alice" />
<Greeting name="Bob" />

Props = Arguments de fonction

Pensez aux props comme aux arguments d'une fonction :

javascript
// Fonction JavaScript normale
function greet(name) {
  return `Bonjour ${name}`;
}
greet('Alice'); // "Bonjour Alice"

// Composant React avec prop
function Greeting({ name }) {
  return <h1>Bonjour {name}</h1>;
}
<Greeting name="Alice" /> // Affiche "Bonjour Alice"

Passer des props

Vous passez des props comme des attributs HTML.

jsx
function App() {
  return (
    <div>
      <Greeting name="Alice" age={25} />
      <Greeting name="Bob" age={30} />
    </div>
  );
}

Types de props

Chaînes de caractères :

jsx
<UserCard name="Alice" />

Nombres, booléens, objets, tableaux :

jsx
<ProductCard price={99} inStock={true} />
<UserCard user={{ name: 'Alice', age: 25 }} />

Attention aux types

Chaînes : Avec ou sans accolades

jsx
<UserCard name="Alice" />  // ✅
<UserCard name={'Alice'} /> // ✅ Équivalent

Autres types : Toujours avec accolades

jsx
<ProductCard price={99} />        // ✅ Number
<ProductCard price="99" />        // ❌ String "99"

<Toggle enabled={true} />         // ✅ Boolean
<Toggle enabled="true" />         // ❌ String "true"

Comment passe-t-on un nombre en tant que prop ?

Recevoir des props

Méthode 1 : Objet props

jsx
function Greeting(props) {
  return (
    <div>
      <h1>Bonjour {props.name} !</h1>
      <p>Tu as {props.age} ans.</p>
    </div>
  );
}

Méthode 2 : Destructuration (recommandé)

jsx
function Greeting({ name, age }) {
  return (
    <div>
      <h1>Bonjour {name} !</h1>
      <p>Tu as {age} ans.</p>
    </div>
  );
}

Pourquoi la destructuration ?

Avantages :

  • Plus court et lisible
  • Vous voyez immédiatement quelles props sont utilisées
  • Auto-complétion plus facile dans votre éditeur

Valeurs par défaut

Vous pouvez définir des valeurs par défaut pour les props.

jsx
function Button({ text = 'Cliquez-moi', color = 'blue' }) {
  return (
    <button style={{ backgroundColor: color }}>
      {text}
    </button>
  );
}

// Utilisation
<Button />                           // Utilise les valeurs par défaut
<Button text="Envoyer" />            // text="Envoyer", color="blue"
<Button text="Annuler" color="red" /> // Les deux personnalisés

Props en lecture seule

Les props sont immuables : vous ne pouvez jamais les modifier.

jsx
function Greeting({ name }) {
  // ❌ ERREUR : Ne modifiez jamais les props !
  name = name.toUpperCase();

  return <h1>Bonjour {name}</h1>;
}

Les props sont read-only

Règle d'or : Un composant ne doit jamais modifier ses propres props.

jsx
// ❌ Interdit
function Counter({ count }) {
  count = count + 1; // ERREUR !
  return <p>{count}</p>;
}

// ✅ Créez une nouvelle variable si nécessaire
function Counter({ count }) {
  const nextCount = count + 1;
  return <p>Prochain : {nextCount}</p>;
}

Pourquoi ? Les props viennent du parent. Si vous les modifiez, vous créez des bugs imprévisibles.

Peut-on modifier la valeur d'une prop à l'intérieur d'un composant ?

Passer des fonctions en props

Vous pouvez passer des fonctions comme props pour gérer les événements.

jsx
function Button({ onClick, text }) {
  return <button onClick={onClick}>{text}</button>;
}

function App() {
  function handleClick() {
    alert('Bouton cliqué !');
  }

  return <Button onClick={handleClick} text="Cliquez-moi" />;
}

Exemple : Champ de recherche

jsx
function SearchBar({ onSearch }) {
  return (
    <input
      type="text"
      placeholder="Rechercher..."
      onChange={(e) => onSearch(e.target.value)}
    />
  );
}

function App() {
  function handleSearch(searchTerm) {
    console.log('Recherche :', searchTerm);
  }

  return <SearchBar onSearch={handleSearch} />;
}

Convention de nommage

Props de fonction : Préfixez avec on + Action

jsx
<Button onClick={handleClick} />
<Form onSubmit={handleSubmit} />
<Input onChange={handleChange} />
<Modal onClose={handleClose} />

Fonctions de gestion : Préfixez avec handle + Action

jsx
function handleClick() { /* ... */ }
function handleSubmit() { /* ... */ }
function handleChange() { /* ... */ }

Validation des props avec TypeScript

TypeScript offre une vérification à la compilation et une excellente auto-complétion.

tsx
interface UserCardProps {
  name: string;
  age: number;
  email?: string; // Optionnel
}

function UserCard({ name, age, email }: UserCardProps) {
  return (
    <div>
      <h2>{name}</h2>
      <p>{age} ans</p>
      {email && <p>{email}</p>}
    </div>
  );
}

Pourquoi TypeScript ?

Avantages :

  • Erreurs détectées avant même de lancer l'app
  • Auto-complétion parfaite dans votre éditeur
  • Documentation implicite de vos composants
  • Plus de sécurité et moins de bugs

Vous verrez TypeScript en détail dans la section dédiée.

Exemple pratique : Carte de produit

jsx
function ProductCard({ name, price, image, onAddToCart }) {
  return (
    <div className="product-card">
      <img src={image} alt={name} />
      <h3>{name}</h3>
      <p className="price">{price}</p>
      <button onClick={() => onAddToCart({ name, price })}>
        Ajouter au panier
      </button>
    </div>
  );
}

// Utilisation
function App() {
  function handleAddToCart(product) {
    console.log('Ajouté:', product);
  }

  return (
    <ProductCard
      name="Laptop"
      price={999}
      image="laptop.jpg"
      onAddToCart={handleAddToCart}
    />
  );
}

Bonnes pratiques

Conseils pour bien utiliser les props

Destructurez les props

jsx
// ✅ Bon
function User({ name, email }) { /* ... */ }

// ❌ Moins bon
function User(props) {
  return <div>{props.name}, {props.email}</div>;
}

Utilisez des valeurs par défaut

jsx
function Button({ text = 'OK', variant = 'primary' }) { /* ... */ }

Ne modifiez jamais les props

jsx
// ❌ Interdit
function Component({ value }) {
  value = value + 1; // NON !
}

Gardez les props simples

jsx
// ✅ Bon : Props simples et claires
<UserCard name="Alice" age={25} />

// ❌ Trop de props
<UserCard firstName="Alice" lastName="Dupont" age={25} email="..." phone="..." />

// ✅ Mieux : Groupez dans un objet
<UserCard user={{ name: 'Alice', age: 25, email: '...' }} />

Résumé

À retenir

Props = Arguments de fonction

  • Permettent de passer des données du parent vers l'enfant
  • Syntaxe : <Component prop="value" />
  • Valeurs non-string avec accolades : count={5}, enabled={true}

Recevoir les props

  • Objet props : function Component(props) { props.name }
  • Destructuration (recommandé) : function Component({ name, age })
  • Valeurs par défaut : function Component({ name = 'Anonyme' })

Règles importantes

  • Les props sont en lecture seule (immuables)
  • Ne jamais modifier les props reçues
  • Les fonctions peuvent être passées en props (conventions : onClick, handleClick)

Validation avec TypeScript

  • Typage à la compilation
  • Auto-complétion et détection d'erreurs
  • Documentation implicite des composants

Les props sont essentielles pour créer des composants réutilisables et flexibles !

Ressources