Menu

Komponenty React: komponenty funkcyjne z przykładami

Komponent Reacta to funkcja JavaScript, która zwraca JSX. Dowiedz się, jak pisać i nazywać komponenty funkcyjne, składać je w drzewo, dzielić na pliki, utrzymywać je czystymi i czym komponenty różnią się od elementów.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Komponent Reacta to funkcja JavaScript, która zwraca JSX: fragment UI wielokrotnego użytku, taki jak przycisk, karta albo cała strona. Używasz go jak tagu HTML, <Profile />, a React wywołuje funkcję, żeby dowiedzieć się, co umieścić na ekranie. Aplikacje buduje się, wkładając komponenty do innych komponentów.

App renderuje Profile dwa razy, a każdy Profile renderuje Avatar. Zmień inicjały wewnątrz Avatar, a oba profile się zaktualizują, bo dzielą jedną definicję. Na razie każda osoba na tej liście jest taka sama; następna strona, propsy, pokazuje, jak przekazać każdej kopii jej własne dane.

Pisanie komponentu

Komponent funkcyjny ma dwa wymagania:

  1. Jego nazwa zaczyna się wielką literą: Profile, a nie profile.
  2. Zwraca coś, co React potrafi wyrenderować: JSX, tekst, liczbę, null (nic nie renderuj) albo tablicę takich wartości.
function Welcome() {
    return <h1>Welcome back</h1>;
}

// Arrow functions work the same way
const Welcome = () => <h1>Welcome back</h1>;

Gdy JSX zajmuje kilka linii, owiń go w nawiasy po return. Bez nich return, po którym następuje znak nowej linii, zwraca undefined, a wszystko po nim jest ignorowane.

Dlaczego nazwa musi zaczynać się wielką literą

JSX patrzy na pierwszą literę tagu. Mała litera oznacza wbudowany element HTML, więc <div> zostaje <div>. Wielka litera oznacza „zmienną w zasięgu", więc <Profile /> wywołuje twoją funkcję Profile. Nazwij komponent małą literą, a React utworzy zamiast niego nieznany element HTML o tej nazwie:

Druga linia pokazuje tylko swoją etykietę, a konsola pokazuje tylko Greeting ran. React wstawił na stronę pusty tag <greeting> i nigdy nie wywołał funkcji pisanej małą literą. Build deweloperski ostrzega też, że The tag <greeting> is unrecognized in this browser; podgląd działa jak build produkcyjny, więc widzisz tylko brakujący tekst. Zmień nazwę funkcji na Greetings, a tag na <Greetings />, żeby to naprawić.

Składanie komponentów

Komponenty są przeznaczone do zagnieżdżania. Strona to drzewo: App na górze, potem elementy układu, potem mniejsze części aż do pojedynczych przycisków. Każdy komponent wie tylko o częściach, które renderuje bezpośrednio, więc możesz analizować je po kolei.

Każdy LikeButton ma własny stan, więc polubienie jednego posta nie rusza pozostałych. Żeby dodać przycisk udostępniania do każdego posta, piszesz go raz i dodajesz <ShareButton /> wewnątrz Post.

Kiedy podzielić komponent

Nie ma sztywnej reguły, ale kilka znaków mówi, że fragment zasługuje na własny komponent: te same znaczniki pojawiają się w dwóch miejscach, fragment JSX ma własny stan (jak przycisk polubienia powyżej) albo funkcja urosła tak, że musisz przewijać, żeby zobaczyć jej return. Dzielenie według tych zasad sprawia, że każdy komponent jest na tyle mały, żeby zmieścić się na jednym ekranie. Zbyt wczesny podział niewiele kosztuje: komponent to tylko funkcja, więc ponowne połączenie dwóch jest łatwe.

Eksportowanie i importowanie komponentów

Edytory tutaj mają jeden plik, ale prawdziwy projekt trzyma komponenty w osobnych plikach. Plik może mieć jeden eksport domyślny i dowolną liczbę eksportów nazwanych:

// Avatar.jsx
export default function Avatar({ initials }) {
    return <div className="avatar">{initials}</div>;
}

// Badge.jsx
export function Badge({ label }) {
    return <span className="badge">{label}</span>;
}
export function NewBadge() {
    return <Badge label="new" />;
}
// Profile.jsx
import Avatar from './Avatar.jsx';
import { Badge, NewBadge } from './Badge.jsx';

export default function Profile() {
    return (
        <div>
            <Avatar initials="AL" />
            <Badge label="admin" />
            <NewBadge />
        </div>
    );
}

Eksport domyślny można zaimportować pod dowolną nazwą; eksport nazwany importuje się w nawiasach klamrowych pod dokładną nazwą. Zespoły zwykle wybierają jeden styl i się go trzymają. Nazwy plików zwykle odpowiadają komponentowi: Avatar.jsx eksportuje Avatar.

Utrzymuj komponenty czystymi

React oczekuje, że komponent podczas renderowania zachowuje się jak czysta funkcja: te same propsy i stan dają ten sam JSX, a renderowanie nie zmienia niczego, co istniało przed jego uruchomieniem. React może renderować komponent wiele razy, w chwilach, których nie kontrolujesz, więc komponent, który podczas renderowania zmienia zewnętrzne zmienne, za każdym razem daje inny wynik.

Nieczyste kubki zaczynają od 1, 2, 3. Kliknij przycisk: nic w gościach się nie zmieniło, a jednak nieczysta lista pokazuje teraz 4, 5, 6, bo każde renderowanie dodało coś do współdzielonej zmiennej guest. Czyste kubki dostają numer z propsów i pozostają poprawne. W trybie deweloperskim Strict Mode renderuje każdy komponent dwa razy, żeby ujawnić właśnie taki błąd; podgląd działa jak build produkcyjny, więc tutaj rozjazd widać dopiero przy ponownym renderowaniu.

Zmienianie rzeczy jest w porządku, tylko nie podczas renderowania. Aktualizuj stan w handlerach zdarzeń, a z zewnętrznym światem (timery, subskrypcje, tytuł dokumentu) komunikuj się w efektach.

Komponenty a elementy

Komponent to funkcja, Profile. Element to to, co tworzy JSX, gdy piszesz <Profile />: mały obiekt mówiący „wyrenderuj Profile z tymi propsami". React tworzy elementy, wywołuje komponenty, które one wskazują, i zamienia wynik w DOM. Nigdy sam nie wywołujesz komponentu jako Profile(); piszesz <Profile /> i pozwalasz Reactowi go wywołać, żeby mógł śledzić jego stan i miejsce w drzewie.

To miejsce ma znaczenie. Ten przykład definiuje komponent wewnątrz innego komponentu, co jest częstym błędem:

Wpisz coś, a potem kliknij przycisk: twój tekst znika. Każde renderowanie App tworzy zupełnie nową funkcję NameField, więc React widzi w tym miejscu inny typ komponentu i wyrzuca stary razem z jego stanem. Przenieś NameField nad App, na najwyższy poziom pliku, a tekst przetrwa każde kliknięcie. Strona o renderowaniu wyjaśnia, jak React decyduje, co zachować.

Komponenty funkcyjne i komponenty klasowe

Zanim w React 16.8 pojawiły się hooki, komponenty potrzebujące stanu pisało się jako klasy:

import { Component } from 'react';

class Welcome extends Component {
    render() {
        return <h1>Hello, {this.props.name}</h1>;
    }
}

Komponenty klasowe nadal działają w React 19 i spotkasz je w starszych projektach oraz w granicach błędów (error boundaries), które wciąż wymagają klasy. Nowy kod używa komponentów funkcyjnych z hookami takimi jak useState i useEffect, które wykonują te same zadania przy mniejszej ilości kodu. Strona o komponentach klasowych przypisuje każdej funkcji klasy odpowiadający jej hook.

Najczęściej zadawane pytania

Co to jest komponent w React?

Komponent to fragment UI wielokrotnego użytku, napisany jako funkcja JavaScript zwracająca JSX. Używasz go jak tagu HTML, <Profile />, a React wywołuje funkcję, żeby dowiedzieć się, co narysować.

Dlaczego nazwy komponentów Reacta muszą zaczynać się wielką literą?

JSX po pierwszej literze decyduje, czym jest tag. Tag pisany małą literą, taki jak <profile />, jest traktowany jako element HTML o nazwie profile, a twoja funkcja nigdy nie zostaje wywołana. Tag z wielkiej litery, taki jak <Profile />, odnosi się do twojego komponentu.

Czym różnią się komponenty funkcyjne od klasowych?

Oba opisują UI. Komponenty funkcyjne to zwykłe funkcje i używają hooków do stanu i efektów; komponenty klasowe rozszerzają React.Component i używają metod takich jak render i componentDidMount. Nowy kod używa komponentów funkcyjnych.

Co to jest czysty komponent w React?

Czysty komponent zwraca ten sam JSX dla tych samych propsów i stanu i podczas renderowania nie zmienia niczego poza sobą. React na tym polega, żeby renderować komponenty tak często, jak potrzebuje, bez niespodzianek.

Czy mogę zdefiniować komponent wewnątrz innego komponentu?

Unikaj tego. Komponent zdefiniowany wewnątrz innego jest nową funkcją przy każdym renderowaniu, więc React za każdym razem traktuje go jako inny komponent i resetuje jego stan. Definiuj komponenty na najwyższym poziomie pliku.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ