Composants polymorphes avec la propriété « as »
Typez la propriété « as » afin qu’un Button soit rendu comme ou tout en conservant les types de propriétés corrects.
Composants polymorphes avec la propriété « as » est une leçon React Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage React Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours React Academy comprend 4 leçons au total.
Qu'est-ce qu'un composant polymorphe ?
Un composant polymorphe s'affiche sous la forme de différents éléments HTML ou composants en fonction d'une propriété as — par exemple, un Button qui s'affiche comme <a> ou <button> tout en conservant des types TypeScript corrects.
Propriété as simple (sans TypeScript)
Une implémentation polymorphe de base sans génériques — elle perd la sûreté de typage, mais montre le concept.
function Box({ as: Tag = 'div', children, ...props }) {
return <Tag {...props}>{children}</Tag>;
}
// Usage:
<Box as="section" className="hero">...</Box>
<Box as="article">...</Box>Propriété as typée avec des génériques
Ajoutez un paramètre de type générique pour déduire les propriétés correctes, quel que soit l'élément rendu par as.
type PolymorphicProps<E extends React.ElementType> = {
as?: E;
} & Omit<React.ComponentPropsWithoutRef<E>, 'as'>;
function Box<E extends React.ElementType = 'div'>({
as,
...props
}: PolymorphicProps<E>) {
const Tag = as ?? 'div';
return <Tag {...props} />;
}Prise en charge de ref
Ajoutez la prise en charge de forwardRef tout en conservant le typage polymorphe.
type PolymorphicRef<E extends React.ElementType> = React.ComponentPropsWithRef<E>['ref'];
type PolymorphicPropsWithRef<E extends React.ElementType, P = {}> = P &
Omit<React.ComponentPropsWithRef<E>, keyof P> & { as?: E };
const Button = React.forwardRef(
<E extends React.ElementType = 'button'>(
{ as, ...props }: PolymorphicPropsWithRef<E>,
ref: PolymorphicRef<E>
) => {
const Tag = as ?? 'button';
return <Tag ref={ref} {...props} />;
}
);Inférence TypeScript en pratique
Lorsque vous définissez as='a', TypeScript sait que le composant accepte les propriétés propres aux ancres, comme href et target, mais pas celles propres aux boutons, comme disabled.
// TypeScript allows href because as='a':
<Box as="a" href="https://example.com">Link</Box>
// TypeScript errors if you pass href to a div:
<Box as="div" href="...">Error!</Box> // TS: href is not a valid div propÉtendre avec des propriétés personnalisées
Ajoutez les propriétés propres au composant à la base polymorphe en les intégrant à la définition du type.
type TextProps<E extends React.ElementType> = PolymorphicProps<E> & {
size?: 'sm' | 'md' | 'lg';
weight?: 'normal' | 'bold';
};
function Text<E extends React.ElementType = 'p'>({
as,
size = 'md',
weight = 'normal',
className,
...props
}: TextProps<E>) {
const Tag = as ?? 'p';
return (
<Tag
className={[`text-${size}`, `font-${weight}`, className].filter(Boolean).join(' ')}
{...props}
/>
);
}Cas d'utilisation concret : lien rendu comme RouterLink
Un Button qui s'affiche comme le lien de React Router lorsque to est fourni, ou comme un bouton ordinaire dans le cas contraire.
import { Link } from 'react-router-dom';
type ButtonProps =
| { to: string; href?: never } & React.ComponentPropsWithoutRef<typeof Link>
| { href: string; to?: never } & React.ComponentPropsWithoutRef<'a'>
| { to?: never; href?: never } & React.ComponentPropsWithoutRef<'button'>;
function Button({ to, href, ...props }: ButtonProps) {
if (to) return <Link to={to} {...props} />;
if (href) return <a href={href} {...props} />;
return <button type="button" {...props} />;
}Composant Text du système de conception
Un composant polymorphe Text qui utilise <p> par défaut, mais peut s'afficher comme h1–h6, span ou label.
<Text as="h1" size="xl">Page Title</Text>
<Text as="span" weight="bold">Inline bold</Text>
<Text as="label" htmlFor="email">Email</Text> // htmlFor is valid because as='label'Contraintes de la propriété as
Utilisez extends React.ElementType pour accepter à la fois les chaînes représentant des éléments HTML ('div', 'a') et les composants React.
function Card<E extends React.ElementType = 'div'>({ as, ...props }: PolymorphicProps<E>) {
const Tag = as ?? 'div';
return <Tag {...props} />;
}
// Works with HTML elements:
<Card as="section" aria-label="Products" />
// Works with React components:
<Card as={motion.div} animate={{ opacity: 1 }} />Éviter les pièges courants
Ne diffusez pas la propriété as sur l'élément (ce n'est pas un attribut HTML valide). Extrayez-la toujours avant de diffuser les propriétés restantes.
// Bad:
function Box({ as: Tag = 'div', ...props }) {
return <Tag as={...} {...props} />; // 'as' attribute on div is invalid HTML
}
// Good:
function Box({ as: Tag = 'div', ...props }) {
return <Tag {...props} />; // 'as' is used to pick Tag, not passed to element
}Considération de performance
Les composants polymorphes ont un surcoût minimal en matière de performances — la propriété as n'est qu'une variable contenant une chaîne de type d'élément ou une référence de composant.
Vérification rapide
Pourquoi devez-vous déstructurer la propriété as avant de diffuser les propriétés restantes sur l'élément dans un composant polymorphe ?
Récapitulatif
Les composants polymorphes utilisent une propriété générique as?: E extends React.ElementType pour s'afficher comme n'importe quel élément tout en conservant les propriétés TypeScript correctes. Déstructurez as avant de diffuser les propriétés restantes. Utilisez React.ComponentPropsWithoutRef pour inclure tous les attributs propres à l'élément dans le type.
Questions Fréquemment Posées
La leçon « Composants polymorphes avec la propriété « as » » est-elle gratuite ?
Oui — le texte complet de « Composants polymorphes avec la propriété « as » » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours React Academy, passe à CoddyKit PRO. Le cours React Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Composants polymorphes avec la propriété « as » » ?
Typez la propriété « as » afin qu’un Button soit rendu comme ou tout en conservant les types de propriétés corrects. Tu pratiques React Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer React Academy ?
Aucune expérience préalable n'est requise. React Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « Composants polymorphes avec la propriété « as » » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon React Academy ?
Oui. Chaque leçon React Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Unions discriminées pour les variantes de composants
- Types conditionnels et mappés dans React
- Composants polymorphes avec la propriété « as »
- Formulaires sûrs du point de vue des types et contrats de réponses d’API