Główne API Reacta
Obiekt React
jest punktem wejściowym do biblioteki React. Jeśli załadujesz ją używając tagu <script>
, główny interfejs API będzie dostępny w zmiennej globalnej React
. Jeśli używasz standardu ES6, możesz skorzystać ze składni import React from 'react'
. Jeśli używasz starszego standardu ES5, użyj składni var React = require('react')
.
Ogólne informacje
Komponenty
Komponenty reaktowe pozwalają podzielić interfejs użytkownika na niezależne, enkapsulowane elementy, z których możesz korzystać w wielu miejscach. Komponenty w Reakcie mogą być definiowane poprzez dziedziczenie po klasie React.Component
lub React.PureComponent
.
Jeśli nie używasz standardu ES6 do definiowania klas, możesz skorzystać z modułu create-react-class
. W innym rozdziale opisaliśmy sposób na korzystanie z Reacta bez ES6.
Komponenty reactowe można również zdefiniować jako funkcje, a następnie otoczyć:
Tworzenie elementów reactowych
Do opisania wyglądu interfejsu użytkownika polecamy korzystanie ze składni JSX. W JSX elementy są tylko wygodniejszymi odpowiednikami wywołania metody React.createElement()
. Jeśli korzystasz z JSX, prawdopodobnie nigdy nie przyjdzie ci korzystać z tych metody bezpośrednio.
Aby dowiedzieć się więcej na ten temat, zajrzyj do rozdziału pt. “React bez JSX”.
Przekształcanie elementów
React
udostępnia kilka API do manipulowania elementami:
Fragmenty
React
pozwala także renderować wiele komponentów bez konieczności używania komponentu opakowującego.
Referencje (ang. refs)
Suspense
Suspense
pozwala komponentowi “poczekać” na konkretne zdarzenie przez wyrenderowaniem. Obecnie Suspense
obsługuje tylko jeden przypadek użycia: dynamiczne ładowanie komponentów przy użyciu React.lazy
. W przyszłości będzie wspierał także inne przypadki użycia, jak na przykład pobieranie danych.
Hooki
Hooki są nowym dodatkiem w Reakcie 16.8. Pozwalają one używać stanu i innych funkcjonalności Reacta bez użycia klas. Hooki mają dedykowany rozdział w dokumentacji oraz osobny interfejs API:
Dokumentacja
React.Component
React.Component
to klasa bazowa dla komponentów reaktowych, definiowanych przez użycie klasy ze standardu ES6:
class Greeting extends React.Component {
render() {
return <h1>Witaj, {this.props.name}</h1>;
}
}
Lista metod i właściwości związanych z klasą React.Component
znajduje się w dokumentacji API dla React.Component.
React.PureComponent
Klasa React.PureComponent
jest podobna do React.Component
. Różnica między nimi jest taka, że React.Component
nie posiada implementacji metody shouldComponentUpdate()
, natomiast React.PureComponent
implementuje ją z użyciem płytkiego porównania właściwości (ang. props) i stanu.
Jeśli metoda render()
danego komponentu wyświetla ten sam rezultat przy tych samych właściwościach i stanie, możesz przekształcić go na React.PureComponent
, by poprawić wydajność.
Uwaga
Metoda
shouldComponentUpdate()
klasyReact.PureComponent
wykonuje jedynie płytkie porównanie obiektów. Jeśli zawierają one skomplikowaną strukturę danych, może to wprowadzić nieprawidłowości podczas zmian na głębszych poziomach struktury. Korzystaj zPureComponent
tylko, jeśli spodziewasz się prostej struktury właściwości i stanu, lub użyjforceUpdate()
, jeśli wiesz, że dane umieszczone głęboko w strukturze uległy zmianie. Możesz także zastanowić się nad skorzystaniem z niezmiennych obiektów (ang. immutable objects), by ułatwić szybkie porównanie zagnieżdżonych danych.Dodatkowo,
shouldComponentUpdate()
klasyReact.PureComponent
pomija aktualizację właściwości dla całego poddrzewa komponentu. Upewnij się, że wszystkie komponenty potomne również korzystają z tego rozwiązania.
React.memo
const MyComponent = React.memo(function MyComponent(props) {
/* renderuj korzystając z właściwości */
});
React.memo
jest komponentem wyższego rzędu (ang. higher-order component).
Jeśli twój komponent przy takich samych właściwościach zawsze renderuje tę samą strukturę, możesz opakować go w React.memo
w celu poprawy wydajności. Oznacza to, że React pominie renderowanie tego komponentu i użyje jego ostatnio wyrenderowanej wersji.
React.memo
reaguje tylko na zmiany we właściwościach. Jeśli twój komponent funkcyjny opakowany w React.memo
używa hooków useState
, useReducer
lub useContext
, nadal będzie się aktualizował przy zmianie stanu komponentu lub kontekstu.
Domyślnie, komponent wykona jedynie płytkie porównanie obiektów przekazanych we właściwościach. Jeśli chcesz zastosować własny mechanizm porównujący, możesz przekazać odpowiednią funkcję jako drugi argument.
function MyComponent(props) {
/* renderuj korzystając z właściwości */
}
function areEqual(prevProps, nextProps) {
/*
zwróć true, jeśli przekazując nextProps, komponent zwróciłby
taki sam rezultat, jak po przekazaniu prevProps;
w innym przypadku zwróć false
*/
}
export default React.memo(MyComponent, areEqual);
Ta metoda wykorzystywana jest jedynie do optymalizacji wydajności. Nie powinno się używać jej do “zapobiegania” renderowaniu, ponieważ może to doprowadzić do większej ilości błędów.
Uwaga
W odróżnieniu od metody
shouldComponentUpdate()
w komponencie klasowym, funkcjaareEqual
zwracatrue
, jeśli właściwości są jednakowe, lubfalse
, jeśli nie są. Jest to odwrócona logika metodyshouldComponentUpdate
.
createElement()
React.createElement(
type,
[props],
[...children]
)
Tworzy i zwraca nowy element reactowy danego typu. Argument type
może być zarówno nazwą znacznika HTML (np. 'div'
lub 'span'
), komponentem reaktowym (klasą lub funkcją), jak i fragmentem reaktowym.
Kod pisany w JSX jest konwertowany do wywołań funkcji React.createElement()
. Jeśli korzystasz z JSX, w większości przypadków nie będziesz bezpośrednio wywoływać React.createElement()
. Przeczytaj rozdział pt. “React bez JSX”, aby dowiedzieć się więcej.
cloneElement()
React.cloneElement(
element,
[config],
[...children]
)
Zacznij od sklonowania i zwrócenia elementu reactowego przy pomocy argumentu element
. config
powinien zawierać wszystkie nowe właściwości, key
lub ref
. Nowo utworzony element będzie posiadał pierwotne właściwości scalone płytko z nowymi. Nowe elementy potomne zastąpią obecne. key
oraz ref
z pierwotnego elementu zostaną zachowane, jeśli nie przekażesz ich w config
.
Wywołanie React.cloneElement()
jest niemal równoznaczne z napisaniem:
<element.type {...element.props} {...props}>{children}</element.type>
Jednakże zachowuje on także wszystkie referencje ref
. Oznacza to, że jeśli jeden z komponentów potomnych posiada ref
, nie zostanie on przypadkowo zabrany z jednego z przodków. Nowy element będzie posiadał ten sam ref
co przed klonowaniem. Nowy ref
lub key
zastąpią poprzednie, jeśli je przekażesz.
Powyższy interfejs API zastąpił przestarzałą funkcję React.addons.cloneWithProps()
.
createFactory()
React.createFactory(type)
Zwraca funkcję, która tworzy reaktowy element danego typu. Tak jak React.createElement()
, argument type
może być zarówno nazwą znacznika HTML (np. 'div'
lub 'span'
), komponentem reactowym (klasą lub funkcją) lub fragmentem reactowym.
Ta funkcja pomocnicza jest uznawana za przestarzałą i radzimy korzystać z JSX lub bezpośrednio z React.createElement()
.
Jeśli korzystasz z JSX, nie ma potrzeby korzystania z React.createFactory()
. Przeczytaj rozdział pt. React bez JSX, aby dowiedzieć się więcej.
isValidElement()
React.isValidElement(object)
Weryfikuje, czy obiekt jest elementem reactowym. Zwraca true
lub false
.
React.Children
React.Children
udostępnia narzędzia do obsługi struktury danych przekazanej w this.props.children
.
React.Children.map
React.Children.map(children, function[(thisArg)])
Wywołuje funkcję na każdym bezpośrednim komponencie potomnych zawartym w children
, z this
ustawionym na thisArg
. Jeśli children
jest tablicą, funkcja zostanie wywołana na każdym elemencie tej tablicy. Jeśli potomek jest wartością null
lub undefined
, metoda ta zamiast tablicy zwróci null
lub undefined
Uwaga
Jeśli
children
jest typuFragment
, zostanie potraktowany jako pojedynczy potomek, nie jak tablica.
React.Children.forEach
React.Children.forEach(children, function[(thisArg)])
Działa tak samo, jak React.Children.map()
, ale nie zwraca tablicy.
React.Children.count
React.Children.count(children)
Zwraca liczbę komponentów w children
, równą liczbie potencjalnych wywołań funkcji zwrotnej (ang. callback) przekazanej do map
lub forEach
.
React.Children.only
React.Children.only(children)
Weryfikuje, czy children
ma tylko jednego potomka (element reactowy), i zwraca go. W innym przypadku metoda rzuci wyjątkiem.
Uwaga:
React.Children.only()
nie akceptuje wartości zwracanej przezReact.Children.map()
, ponieważ jest to tablica, a nie element reactowy.
React.Children.toArray
React.Children.toArray(children)
Zwraca strukturę z children
jako płaską tablicę, z kluczem przypisanym do każdego z potomków. Przydatne, jeśli chcemy manipulować grupą potomków w metodzie renderującej, zwłaszcza jeśli chcemy zmienić ich kolejność lub podzielić przed przekazaniem dalej.
Uwaga:
React.Children.toArray()
zmienia klucze, by zachować semantyczną poprawność zagłębionych tablic podczas przygotowywania płaskiej struktury. Oznacza to, żetoArray
doda prefiks do nazwy każdego klucza, tak by każdy element należał do odpowiedniego zakresu.
React.Fragment
Komponent React.Fragment
pozwala zwrócić wiele elementów w metodzie render()
bez opakowywania ich w dodatkowy element DOM:
render() {
return (
<React.Fragment>
Jakiś tekst.
<h2>Nagłówek</h2>
</React.Fragment>
);
}
Możesz także skorzystać ze skróconego zapisu <></>
. Po więcej informacji zajrzyj do wpisu na blogu - React v16.2.0: Improved Support for Fragments.
React.createRef
React.createRef
tworzy referencję, którą możesz przypiąć do dowolnego elementu reactowego poprzez właściwość ref
.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef(); }
render() {
return <input type="text" ref={this.inputRef} />; }
componentDidMount() {
this.inputRef.current.focus(); }
}
React.forwardRef
React.forwardRef
tworzy komponent reactowy, który przekazuje właściwość ref
do kolejnego komponentu w dół drzewa. Ta technika nie jest zbyt popularna, ale przydatna w dwóch konkretnych przypadkach:
React.forwardRef
przyjmuje funkcję renderującą jako argument. React wywoła tę funkcję, przekazując props
oraz ref
jako argumenty. Funkcja ta powinna zwrócić węzeł reactowy (ang. React node).
const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton"> {props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
W powyższym przykładzie React przekazuje ref
poprzez <FancyButton ref={ref}>
jako drugi argument funkcji renderującej wewnątrz React.forwardRef
. Funkcja renderująca przekaże ref
do elementu <button ref={ref}>
.
W rezultacie, po tym, jak referencja zostanie przypięta przez Reacta, ref.current
będzie wskazywał bezpośrednio na element <button>
.
Aby dowiedzieć się więcej, przeczytaj rozdział poświęcony przekazywaniu referencji.
React.lazy
React.lazy()
pozwala definiować komponenty, które są ładowane dynamicznie. Zmniejsza się w ten sposób rozmiar paczki, ponieważ wyodrębnione zostają komponenty, które nie są używane podczas wstępnego renderowania.
W naszej dokumentacji poświęconej rozdzielaniu kodu zamieściliśmy więcej informacji na ten temat. Ten artykuł również może okazać się pomocny w wyjaśnieniu zasad działania tej metody.
// Ten komponent jest ładowany dynamicznie
const SomeComponent = React.lazy(() => import('./SomeComponent'));
Pamiętaj, że renderowanie “leniwych komponentów” (ang. lazy components) wymaga użycia komponentu <React.Suspense>
na wyższym poziomie drzewa. W ten sposób definiuje się wskaźnik ładowania.
Uwaga
Używanie
React.lazy
z dynamicznymi importami wymaga, by w środowisku JS dostępna była klasaPromise
. Będzie to wymagało użycia tzw. “łatek” (ang. polyfill) dla przeglądarki IE11 i starszych.
React.Suspense
React.Suspense
pozwala zdefiniować wskaźnik ładowania, w razie gdyby któryś z komponentów poniżej nie był jeszcze gotowy do wyrenderowania. Obecnie jedynym przypadkiem użycia <React.Suspense>
jest dynamiczne ładowanie komponentów.
// Ten komponent jest ładowany dynamicznie
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
// Wyświetla <Spinner> dopóki OtherComponent nie zostanie załadowany
<React.Suspense fallback={<Spinner />}>
<div>
<OtherComponent />
</div>
</React.Suspense>
);
}
W naszej dokumentacji poświęconej rozdzielaniu kodu zamieściliśmy więcej informacji na ten temat. Zwróć uwagę na to, że komponenty lazy
mogą być zawarte w drzewie wiele poziomów poniżej Suspense
. Dobrą praktyką jest umieszczanie <Suspense>
w miejscu, w którym powinien pojawić się wskaźnik ładowania, natomiast lazy()
w miejscu, w którym chcesz rozdzielić kod.
Mimo że nie jest to obecnie wspierane, w planach jest wykorzystanie Suspense
przy pobieraniu danych. Więcej możesz dowiedzieć się z naszego planu działania.
Uwaga:
React.lazy()
oraz<React.Suspense>
nie są jeszcze wspierane przezReactDOMServer
. Ograniczenie to zostanie wyeliminowane w przyszłości.