React Academy · Oppitunti

Geneeriset komponentit ja utiliteettityypit

Kirjoittakaa uudelleenkäytettäviä geneerisiä komponentteja ja käyttäkää PropsWithChildren-, ComponentProps- ja Omit-tyyppejä.

Oppitunti 3/413 vaihetta

Geneeriset komponentit ja utiliteettityypit on ilmainen React Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu React Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. React Academy-kurssilla on yhteensä 4 oppituntia.

Miksi geneerisiä komponentteja?

Geneeriset komponentit mukautuvat eri tietotyyppeihin säilyttäen täyden tyyppiturvallisuuden. Esimerkiksi tyypitetty lista, valitsin tai taulukko voi toimia minkä tahansa tietorakenteen kanssa.

Yksinkertainen geneerinen lista

Käytä funktiossa tyyppiparametria T, jotta listakomponentti voi renderöidä minkä tahansa tyyppisiä alkioita.

interface ListProps<T> {
  items: T[];
  renderItem: (item: T, index: number) => React.ReactNode;
  keyExtractor: (item: T) => string;
}

function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
  return (
    <ul>
      {items.map((item, i) => (
        <li key={keyExtractor(item)}>{renderItem(item, i)}</li>
      ))}
    </ul>
  );
}

Geneeristen tyyppien rajoittaminen

Käytä extends-määrettä rajoitusten lisäämiseen, jotta TypeScript tietää, mitä ominaisuuksia tyypillä on oltava.

interface SelectProps<T extends { id: string; label: string }> {
  options: T[];
  value: T | null;
  onChange: (option: T) => void;
}

function Select<T extends { id: string; label: string }>(
  { options, value, onChange }: SelectProps<T>
) {
  return (
    <select value={value?.id} onChange={e => onChange(options.find(o => o.id === e.target.value)!)}>
      {options.map(o => <option key={o.id} value={o.id}>{o.label}</option>)}
    </select>
  );
}

PropsWithChildren

React.PropsWithChildren<P> lisää children?: React.ReactNode-määrityksen mihin tahansa propsityyppiin. Se on hyödyllinen wrapper-komponenteissa.

function Card({ title, children }: React.PropsWithChildren<{ title: string }>) {
  return (
    <div className="card">
      <h2>{title}</h2>
      {children}
    </div>
  );
}

ComponentProps

React.ComponentProps<typeof Component> poimii olemassa olevan komponentin propsit. Tämä on hyödyllistä, kun haluat laajentaa komponenttia tai tehdä siitä wrapperin.

import { Button } from './Button';

type ExtendedButtonProps = React.ComponentProps<typeof Button> & {
  loading?: boolean;
};

function LoadingButton({ loading, children, ...props }: ExtendedButtonProps) {
  return (
    <Button {...props} disabled={loading || props.disabled}>
      {loading ? <Spinner /> : children}
    </Button>
  );
}

ComponentPropsWithoutRef

React.ComponentPropsWithoutRef<'input'> poimii HTML-elementin propsit ilman ref-propsia. Se sopii erityisen hyvin HTML-elementtien ympärille tehtäviin wrapper-komponentteihin.

type InputProps = React.ComponentPropsWithoutRef<'input'> & {
  label: string;
  error?: string;
};

function FormInput({ label, error, ...inputProps }: InputProps) {
  return (
    <div>
      <label>{label}</label>
      <input {...inputProps} />
      {error && <span className="error">{error}</span>}
    </div>
  );
}

Omit ja Pick

Käytä Omit<T, Keys>-tyyppiä tiettyjen propsien poistamiseen ja Pick<T, Keys>-tyyppiä vain tiettyjen propsien säilyttämiseen olemassa olevasta tyypistä.

interface UserCardProps {
  id: string;
  name: string;
  email: string;
  avatar: string;
  role: string;
}

// Only expose non-sensitive fields:
type PublicUserCardProps = Omit<UserCardProps, 'email' | 'role'>;
// Or pick exactly what you need:
type AvatarProps = Pick<UserCardProps, 'name' | 'avatar'>;

Partial ja Required

Partial<T> tekee kaikista propseista valinnaisia, mikä on hyödyllistä päivityslomakkeissa. Required<T> tekee kaikista propseista pakollisia.

interface UserFormData { name: string; email: string; bio: string; }

// For update: only send changed fields
type UserUpdatePayload = Partial<UserFormData>;

// For create: all fields are mandatory
type UserCreatePayload = Required<UserFormData>;

Record tyypitettyihin sanakirjoihin

Record<Keys, Value> luo oliotyypin, jolla on tietyt avaintyypit. Se on hyödyllinen hakemistokartoissa ja käännöksissä.

type Status = 'idle' | 'loading' | 'success' | 'error';

const statusLabels: Record<Status, string> = {
  idle: 'Ready',
  loading: 'Loading...',
  success: 'Done!',
  error: 'Something went wrong',
};

ReturnType hook-tyyppeihin

Käytä tyyppiä ReturnType<typeof useMyHook> mukautetun hookin paluutyypin päättelemiseen ilman tyypin manuaalista toistamista.

function useCounter(initial: number) {
  const [count, setCount] = useState(initial);
  return { count, increment: () => setCount(c => c + 1) };
}

type CounterHook = ReturnType<typeof useCounter>;
// { count: number; increment: () => void }

Geneerinen taulukkokomponentti

Täysin tyyppiturvallinen datataulukko toimii minkä tahansa rivirakenteen kanssa, päättelee sarakeavaimet ja tarjoaa silti automaattisen täydennyksen.

interface Column<T> {
  key: keyof T;
  header: string;
  render?: (value: T[keyof T], row: T) => React.ReactNode;
}

function DataTable<T extends object>({ data, columns }: { data: T[]; columns: Column<T>[] }) {
  return (
    <table>
      <thead><tr>{columns.map(c => <th key={String(c.key)}>{c.header}</th>)}</tr></thead>
      <tbody>{data.map((row, i) => (
        <tr key={i}>{columns.map(c => <td key={String(c.key)}>{c.render ? c.render(row[c.key], row) : String(row[c.key])}</td>)}</tr>
      ))}</tbody>
    </table>
  );
}

Pikatarkistus

Mikä utility-tyyppi poistaa määritetyt avaimet olemassa olevasta TypeScript-interfacesta?

Kertaus

Geneeriset komponentit käyttävät tyyppiparametreja säilyttääkseen tyyppiturvallisuuden eri tietorakenteissa. Utility-tyypit, kuten Omit, Pick, Partial, ComponentProps ja PropsWithChildren, poistavat tarpeen toistaa tyyppejä käsin ja tekevät komponenttien rajapinnoista helpommin yhdisteltäviä.

Aloita maksutta

Opi React tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
88
Oppitunnit
324

Usein kysytyt kysymykset

Onko oppitunti ”Geneeriset komponentit ja utiliteettityypit” ilmainen?

Kyllä – oppitunnin ”Geneeriset komponentit ja utiliteettityypit” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko React Academy-kurssin, päivitä CoddyKit PROhon. React Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Geneeriset komponentit ja utiliteettityypit”?

Kirjoittakaa uudelleenkäytettäviä geneerisiä komponentteja ja käyttäkää PropsWithChildren-, ComponentProps- ja Omit-tyyppejä. Harjoittelet React Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni React Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin React Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”Geneeriset komponentit ja utiliteettityypit”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä React Academy-oppitunnilla?

Kyllä. Jokainen React Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Propsien ja komponenttien paluutyyppien tyypitys
  2. Tapahtumien ja refien tyypitys TypeScriptissä
  3. Geneeriset komponentit ja utiliteettityypit
  4. Contextien ja Custom Hooksien tyypitys
← Takaisin: React Academy