React Academy · Lektion

Polymorfe komponenter med 'as'-prop

Typ 'as'-proppen, så en Button kan rendere som eller , samtidig med at de korrekte proptyper bevares.

Lektion 3 af 413 trin

Polymorfe komponenter med 'as'-prop er en gratis React Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i React Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. React Academy-kurset indeholder 4 lektioner i alt.

Hvad er en polymorf komponent?

En polymorf komponent gengiver forskellige HTML-elementer eller komponenter baseret på en as-prop — f.eks. en Button, der gengives som <a> eller <button>, samtidig med at de korrekte TypeScript-typer bevares.

Simpel as-prop (uden TypeScript)

En grundlæggende polymorf implementering uden generiske typer — den mister typesikkerhed, men viser konceptet.

function Box({ as: Tag = 'div', children, ...props }) {
  return <Tag {...props}>{children}</Tag>;
}

// Usage:
<Box as="section" className="hero">...</Box>
<Box as="article">...</Box>

Typet as-prop med generiske typer

Tilføj en generisk typeparameter for at udlede de korrekte props for det element, som as gengives som.

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} />;
}

Med understøttelse af ref

Tilføj understøttelse af forwardRef, samtidig med at den polymorfe typning bevares.

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} />;
  }
);

TypeScript-udledning i praksis

Når du angiver as='a', ved TypeScript, at komponenten accepterer ankerspecifikke props som href og target, men ikke knapspecifikke props som 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

Udvidelse med brugerdefinerede props

Tilføj komponentspecifikke props sammen med den polymorfe grundtype ved at sprede dem ind i typedefinitionen.

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}
    />
  );
}

Praktisk anvendelse: Link, der gengives som RouterLink

En Button, der gengives som React Routers Link, når to er angivet, eller som en almindelig knap ellers.

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} />;
}

Tekstkomponent til et designsystem

En polymorf Text-komponent, der som standard bruger <p>, men kan gengives som h1–h6, span eller 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'

Begrænsninger for as-prop

Brug extends React.ElementType for at acceptere både strenge for HTML-elementer ('div', 'a') og React-komponenter.

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 }} />

Undgå almindelige faldgruber

Spre ikke as-proppen videre til elementet (det er ikke en gyldig HTML-attribut). Destrukturér den altid, før du spreder de resterende props.

// 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
}

Ydeevneovervejelse

Polymorfe komponenter har et minimalt ydeevneoverhead — as-proppen er blot en variabel, der indeholder en streng med en elementtype eller en komponentreference.

Hurtigt tjek

Hvorfor bør du destrukturere as-proppen, før du spreder de resterende props på elementet i en polymorf komponent?

Opsamling

Polymorfe komponenter bruger en generisk as?: E extends React.ElementType-prop til at gengive ethvert element, samtidig med at de korrekte TypeScript-props bevares. Destrukturér as, før du spreder de resterende props. Brug React.ComponentPropsWithoutRef til at medtage alle elementspecifikke attributter i typen.

Gratis at komme i gang

Lær React med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
88
Lektioner
324

Ofte stillede spørgsmål

Er lektionen “Polymorfe komponenter med 'as'-prop” gratis?

Ja — hele teksten til “Polymorfe komponenter med 'as'-prop” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af React Academy-kurset, skal du opgradere til CoddyKit PRO. React Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Polymorfe komponenter med 'as'-prop”?

Typ 'as'-proppen, så en Button kan rendere som eller , samtidig med at de korrekte proptyper bevares. Du øver dig i React Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på React Academy?

Der kræves ingen tidligere erfaring. React Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Polymorfe komponenter med 'as'-prop”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne React Academy-lektion?

Ja. Alle React Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Diskriminerede unions til komponentvarianter
  2. Betingede og mappede typer i React
  3. Polymorfe komponenter med 'as'-prop
  4. Typesikre formularer og API-responskontrakter
← Tilbage til React Academy