03

Props

Passer des données entre composants (Lecture seule)

Le concept : Les Props (propriétés) sont le système de communication de React. C'est un flux de données strictement unidirectionnel : elles descendent du composant Parent vers le composant Enfant, comme une cascade. Elles sont immuables (en lecture seule) par l'enfant, garantissant la prévisibilité de votre application.

Parent user={obj} Child
💡 Comprendre les Props

Les props (propriétés) sont le mécanisme par lequel un composant parent passe des données à un composant enfant. Pensez-y comme aux arguments d'une fonction.

Les props sont immuables : un enfant ne doit jamais modifier les props qu'il reçoit. Si une donnée doit changer, elle doit être dans le state du composant qui la possède.

On peut passer n'importe quel type JS via les props : string, number, boolean, objet, tableau, fonction, ou même un composant React.

Bases des Props
// Passer des props au composant
<UserCard
    name="Alice"
    age={28}
    isAdmin={true}
    tags={['React', 'TypeScript']}
    onClick={handleClick}
/>

// Recevoir et utiliser les props
function UserCard(props) {
    return <h2>{props.name}, {props.age} ans</h2>;
}

✂️ Destructuring des Props

Destructuring dans les paramètres
// ✅ Recommandé : destructuring direct
function UserCard({ name, age, isAdmin }) {
    return (
        <div>
            <h2>{name}</h2>
            <p>{age} ans</p>
            {isAdmin && <span>👑 Admin</span>}
        </div>
    );
}
Valeurs par défaut (default props)
// Avec l'opérateur = lors du destructuring
function Button({
    label = "Cliquer",
    variant = "primary",
    disabled = false,
    onClick
}) {
    return (
        <button
            className={`btn btn-${variant}`}
            disabled={disabled}
            onClick={onClick}
        >
            {label}
        </button>
    );
}

🔁 Patterns avancés

Spread Props (...rest)
// Passer toutes les props non destructurées
function InputField({ label, ...rest }) {
    return (
        <div>
            <label>{label}</label>
            <input {...rest} />
        </div>
    );
}

// `rest` contient tout sauf `label`
<InputField label="Email" type="email"
    placeholder="votre@email.com" required />
Render Props (fonctions enfants)
// Passer une fonction comme prop
function DataLoader({ url, render }) {
    const [data] = useFetch(url);
    return render(data); // Inversion de contrôle
}

// Utilisation
<DataLoader
    url="/api/users"
    render={(users) => (
        <UserList data={users} />
    )}
/>

🛡️ Validation des Props (PropTypes)

PropTypes — Valider en développement
import PropTypes from 'prop-types';

function UserCard({ name, age, avatar, onDelete }) { ... }

UserCard.propTypes = {
    name:     PropTypes.string.isRequired,     // Obligatoire
    age:      PropTypes.number,                // Optionnel
    avatar:   PropTypes.string,
    onDelete: PropTypes.func.isRequired,
    tags:     PropTypes.arrayOf(PropTypes.string),
    status:   PropTypes.oneOf(['active', 'inactive']),
};

// En TypeScript, on utilise des types/interfaces à la place :
interface UserCardProps {
    name: string;
    age?: number;
    onDelete: () => void;
}
⚠️ Props vs State — Règle simple : la donnée appartient au composant qui la crée (state). Elle est passée via les props aux enfants qui ne font que l'afficher. Un enfant ne mutate jamais les props.