Komponent klasowy to klasa JavaScript, która rozszerza React.Component i zwraca JSX z metody render(). Odczytuje propsy z this.props, trzyma stan w this.state i aktualizuje go przez this.setState(). W nowym kodzie zastąpiły je komponenty funkcyjne z hookami, ale klasy nadal są w pełni obsługiwane, pojawiają się w wielu starszych projektach i są jedynym sposobem na napisanie granicy błędów.
Każdy licznik trzyma własny stan. Dodaj trzeci <Counter label="Plums" />, a też zacznie od 0.
Budowa komponentu klasowego
import { Component } from 'react';
class Welcome extends Component {
static defaultProps = { name: 'stranger' };
constructor(props) {
super(props); // required before using this
this.state = { visits: 1 };
}
render() {
return <h1>Hello, {this.props.name}. Visit #{this.state.visits}</h1>;
}
}
- Klasa rozszerza
Component(alboReact.Componentprzyimport React from 'react'). render()jest wymagane. Musi być czyste, jak ciało komponentu funkcyjnego: czytathis.propsithis.state, zwraca JSX.this.propszawiera propsy. Są tylko do odczytu.- Stan można ustawić w
constructor(najpierw wywołajsuper(props)) albo, co dziś częstsze, jako pole klasy:state = { visits: 1 };. static defaultPropsnadal działa dla klas w React 19 (usunięto je tylko dla komponentów funkcyjnych).
this.setState scala obiekty i może przyjąć funkcję aktualizującą
setState robi dwie rzeczy inaczej niż setter z useState. Scala przekazany obiekt z bieżącym stanem, więc aktualizujesz tylko klucze, które wymienisz. I jak każda aktualizacja stanu w React nie jest stosowany od razu, więc używaj formy z funkcją aktualizującą, gdy następna wartość zależy od poprzedniej.
"+3 with objects" dodaje jeden, bo wszystkie trzy wywołania czytają to samo this.state.likes. "+3 with updaters" dodaje trzy. "Move to Paris" zachowuje name i likes (scalanie), ale gubi zip, bo scalanie sięga tylko jednego poziomu. Napisz address: { ...this.state.address, city: 'Paris' }, żeby go zachować. Opcjonalny drugi argument setState uruchamia się po aktualizacji, a konsola pokazuje tam nowy adres.
Wiązanie handlerów zdarzeń
Metoda przekazana jako onClick={this.handleClick} jest później wywoływana jako zwykła funkcja, bez swojego obiektu, więc this w jej środku ma wartość undefined.
Pierwszy przycisk wypisuje TypeError o odczycie setState z undefined. Drugi działa, bo funkcja strzałkowa w polu klasy przechwytuje this w chwili tworzenia instancji. Starsza poprawka, wciąż częsta w starym kodzie, wiąże metodę w konstruktorze:
constructor(props) {
super(props);
this.state = { on: false };
this.handleClick = this.handleClick.bind(this);
}
Działa też strzałka w linii, onClick={() => this.handleClick()}.
Metody cyklu życia
Klasy reagują na montowanie, aktualizację i odmontowanie przez metody o stałych nazwach. Te, które zobaczysz najczęściej:
componentDidMount(): po tym, jak pierwsze renderowanie jest w DOM. Uruchamiaj timery, subskrypcje, żądania.componentDidUpdate(prevProps, prevState): po każdej aktualizacji. Zanim zaczniesz pracę, porównaj z poprzednimi wartościami, bo inaczej wpadniesz w pętlę.componentWillUnmount(): przed usunięciem. Cofnij to, co uruchomiłcomponentDidMount.shouldComponentUpdate(nextProps, nextState): zwróćfalse, żeby pominąć renderowanie.
Strona o cyklu życia komponentu zawiera pełną listę, kolejność wykonania i komponent, który wypisuje każdą z metod.
Przerabianie klasy na komponent funkcyjny
Oto klasa, która używa wszystkich trzech popularnych metod cyklu życia. Tyka co sekundę, wypisuje log, gdy zmienia się jej prop label, i zatrzymuje timer przy usunięciu.
A to ten sam komponent jako funkcja. Każda metoda cyklu życia staje się częścią efektu, a powiązane setup i czyszczenie stoją obok siebie, zamiast w dwóch metodach.
Oba timery liczą tak samo i wypisują log przy każdej zmianie etykiety. Wersja funkcyjna wypisuje też log raz przy zamontowaniu, bo efekt uruchamia się także po pierwszym renderowaniu. Kroki każdej konwersji:
this.props.xstaje się zdestrukturyzowanym propsem,{ x }.- Każdy klucz
this.statestaje się osobnymuseState. Pamiętaj, że setter zastępuje wartość, a nie scala. - Metody stają się zwykłymi funkcjami wewnątrz komponentu. Nie trzeba niczego wiązać.
componentDidMount,componentDidUpdateicomponentWillUnmountstają się wywołaniamiuseEffect, pogrupowanymi według tego, co robią, a nie według tego, kiedy się uruchamiają.createRefstaje sięuseRef, astatic contextTypezthis.contextstaje sięuseContextalbouse.
Granice błędów zostaw jako klasy; nie mają odpowiednika funkcyjnego.
PureComponent
Zwykły komponent klasowy renderuje się za każdym razem, gdy renderuje się jego rodzic. PureComponent najpierw porównuje nowe propsy i stan z poprzednimi, na jednym poziomie głębokości, i pomija renderowanie, gdy nic się nie zmieniło. To klasowy odpowiednik React.memo.
Kliknij przycisk: wypisuje się tylko PlainLabel rendered, bo PureLabel widzi ten sam text. Przekaż obu text={'hello ' + clicks}, a oba będą renderować się przy każdym kliknięciu.
Porównanie jest płytkie, więc prop, który przy każdym renderowaniu rodzica jest nowym obiektem albo funkcją (style={{ color: 'red' }}, onClick={() => ...}), je unieważnia. To ta sama pułapka co przy React.memo.
Co React 19 usunął z klas
Jeśli utrzymujesz stary kod klasowy, kilka wzorców nie działa już w React 19:
- String refs (
ref="input"zthis.refs.input). UżyjcreateRef()albo ref callback. - Przestarzały kontekst (
contextTypes,childContextTypes,getChildContext). UżyjcreateContextzestatic contextType. propTypessą ignorowane. Użyj TypeScriptu albo własnych sprawdzeń.findDOMNodezniknął. Zamiast tego umieść ref na elemencie DOM.
Stare metody componentWillMount, componentWillReceiveProps i componentWillUpdate też są przestarzałe. Nadal się wykonują, zarówno pod starymi nazwami, jak i z przedrostkiem UNSAFE_ (UNSAFE_componentWillMount i tak dalej), ale są oznaczone jako przestarzałe, a StrictMode przed nimi ostrzega; przenieś ich kod do componentDidMount, componentDidUpdate albo getDerivedStateFromProps.
Najczęściej zadawane pytania
Czy komponenty klasowe są przestarzałe w React?
Nie. Nadal są obsługiwane w React 19 i dalej będą działać, ale dokumentacja Reacta zaleca dla nowego kodu komponenty funkcyjne z hookami. Do granic błędów nadal potrzebujesz klasy.
Czym różnią się komponenty klasowe od funkcyjnych?
Komponent klasowy trzyma stan w this.state, aktualizuje go przez this.setState i reaguje na cykl życia przez nazwane metody. Komponent funkcyjny do tych samych zadań używa hooków (useState, useEffect), nie potrzebuje this i jest krótszy.
Czy setState aktualizuje stan od razu?
Nie. this.setState planuje aktualizację, a React renderuje później, więc zaraz po wywołaniu this.state ma wciąż starą wartość. Przekaż funkcję, this.setState((state) => ...), gdy nowa wartość zależy od starej, albo odczytaj wynik w callbacku podanym jako drugi argument lub w componentDidUpdate.
Dlaczego this ma wartość undefined w moim handlerze zdarzenia?
Metoda klasy przekazana jako onClick={this.handleClick} jest wywoływana bez swojego obiektu, więc this ma wartość undefined. Zdefiniuj handler jako funkcję strzałkową w polu klasy (handleClick = () => { ... }) albo zwiąż go w konstruktorze.
Co to jest PureComponent?
Component, który pomija renderowanie, gdy jego propsy i stan są płytko równe poprzednim. To klasowa wersja React.memo.