Komponenty polimorficzne z propsem 'as'
Typowanie propsa 'as', aby Button renderował się jako lub , przy zachowaniu prawidłowych typów propsów.
Komponenty polimorficzne z propsem 'as' to bezpłatna lekcja React Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej React Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs React Academy zawiera 4 lekcji w sumie.
Czym jest komponent polimorficzny
Komponent polimorficzny renderuje różne elementy HTML lub komponenty w zależności od propsa as — np. komponent Button, który renderuje się jako <a> lub <button>, zachowując przy tym poprawne typy TypeScript.
Prosty props as (bez TypeScriptu)
Podstawowa implementacja polimorficzna bez generyków — traci bezpieczeństwo typów, ale pokazuje tę koncepcję.
function Box({ as: Tag = 'div', children, ...props }) {
return <Tag {...props}>{children}</Tag>;
}
// Usage:
<Box as="section" className="hero">...</Box>
<Box as="article">...</Box>Typowany props as z generykami
Dodaj parametr typu generycznego, aby wywnioskować poprawne propsy dla elementu wskazanego przez 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} />;
}Obsługa ref
Dodaj obsługę forwardRef, zachowując polimorficzne typowanie.
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} />;
}
);Wnioskowanie TypeScriptu w praktyce
Po ustawieniu as='a' TypeScript wie, że komponent akceptuje propsy właściwe dla elementu kotwicy, takie jak href i target, ale nie propsy właściwe dla przycisku, takie jak 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 propRozszerzanie o własne propsy
Dodaj propsy specyficzne dla komponentu obok polimorficznej bazy, uwzględniając je w definicji typu.
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}
/>
);
}Praktyczny przypadek: Link renderowany jako RouterLink
Komponent Button, który renderuje Link biblioteki React Router, gdy podano to, albo zwykły przycisk w przeciwnym razie.
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} />;
}Komponent Text w systemie projektowym
Polimorficzny komponent Text, który domyślnie renderuje się jako <p>, ale może renderować się jako h1–h6, span lub 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'Ograniczenia propsa as
Użyj extends React.ElementType, aby akceptować zarówno ciągi znaków reprezentujące elementy HTML ('div', 'a'), jak i komponenty 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 }} />Unikanie typowych pułapek
Nie rozpraszaj propsa as na elemencie (nie jest poprawnym atrybutem HTML). Zawsze wyodrębnij go przed rozproszeniem pozostałych propsów.
// 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
}Aspekt wydajnościowy
Komponenty polimorficzne mają minimalny narzut wydajnościowy — props as jest po prostu zmienną przechowującą łańcuch znaków typu elementu lub referencję do komponentu.
Szybki sprawdzian
Dlaczego należy wyodrębnić props as przed rozproszeniem pozostałych propsów na elemencie w komponencie polimorficznym?
Podsumowanie
Komponenty polimorficzne używają generycznego propsa as?: E extends React.ElementType, aby renderować dowolny element z zachowaniem poprawnych propsów TypeScriptu. Wyodrębnij as przed rozproszeniem pozostałych propsów. Użyj React.ComponentPropsWithoutRef, aby uwzględnić w typie wszystkie atrybuty właściwe dla danego elementu.
Często zadawane pytania
Czy lekcja „Komponenty polimorficzne z propsem 'as'” jest bezpłatna?
Tak — pełny tekst „Komponenty polimorficzne z propsem 'as'” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu React Academy, przejdź na CoddyKit PRO. Kurs React Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Komponenty polimorficzne z propsem 'as'”?
Typowanie propsa 'as', aby Button renderował się jako lub , przy zachowaniu prawidłowych typów propsów. Ćwiczysz React Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć React Academy?
Nie wymagamy żadnego doświadczenia. React Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Komponenty polimorficzne z propsem 'as'”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji React Academy?
Tak. Każda lekcja React Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Rozłączne sumy dla wariantów komponentów
- Typy warunkowe i mapowane w React
- Komponenty polimorficzne z propsem 'as'
- Formularze bezpieczne typowo i kontrakty odpowiedzi API