Samouczek React: komponenty, hooki i wydajność
Opublikowany: 2022-03-11Jak wskazano w pierwszej części naszego samouczka React, rozpoczęcie pracy z Reactem jest stosunkowo łatwe. Zacznij od użycia Create React App (CRA), rozpocznij nowy projekt i zacznij programować. Niestety, z biegiem czasu możesz trafić w sytuację, w której Twój kod stanie się dość trudny do utrzymania, zwłaszcza jeśli jesteś nowy w React. Komponenty mogą stać się niepotrzebnie duże lub możesz skończyć z elementami, które mogą być komponentami, ale nimi nie są, więc możesz skończyć na pisaniu powtarzającego się kodu tu i tam.
W tym miejscu powinieneś spróbować naprawdę rozpocząć swoją przygodę z React — zaczynając od myślenia o rozwiązaniach programistycznych React.
Za każdym razem, gdy podchodzisz do nowej aplikacji, nowego projektu, który musisz później przekształcić w aplikację React, najpierw spróbuj zdecydować, jakie komponenty będą w twoim szkicu, jak możesz oddzielić szkic, aby łatwiej nimi zarządzać i które elementy są powtarzalne (lub przynajmniej ich zachowanie). Staraj się unikać dodawania kodu, który może być „przydatny w przyszłości” — może to być kuszące, ale taka przyszłość może nigdy nie nadejść i zachowasz tę dodatkową ogólną funkcję/komponent, który ma wiele konfigurowalnych opcji.
Ponadto, jeśli element jest dłuższy niż, powiedzmy, 2-3 wysokość okna, może warto go rozdzielić (jeśli to możliwe) – bo później będzie łatwiej go odczytać.
Kontrolowane i niekontrolowane komponenty w React
W większości aplikacji istnieje potrzeba wprowadzania danych i jakiejś formy interakcji z użytkownikami, która pozwala im coś wpisać, przesłać plik, wybrać pole i tak dalej. React zajmuje się interakcją z użytkownikiem na dwa różne sposoby — komponenty kontrolowane i niekontrolowane .
Wartość kontrolowanych komponentów, jak sugeruje ich nazwa, jest kontrolowana przez React poprzez podanie wartości elementowi, który wchodzi w interakcję z użytkownikiem, podczas gdy niekontrolowane elementy nie otrzymują właściwości value. Dzięki temu mamy jedno źródło prawdy, którym akurat jest stan React, dzięki czemu nie ma rozbieżności między tym, co widzimy na ekranie, a tym, co aktualnie mamy w naszym stanie. Deweloper musi przekazać funkcję, która będzie reagowała na interakcję użytkownika z formularzem, co zmieni jego stan.
class ControlledInput extends React.Component { state = { value: "" }; onChange = (e) => this.setState({ value: e.target.value }); render() { return ( <input value={this.state.value} onChange={this.onChange}/> ); } }
W niekontrolowanych komponentach React nie dbamy o to, jak zmienia się wartość, ale jeśli chcemy poznać dokładną wartość, po prostu uzyskujemy do niej dostęp poprzez ref.
class UncontrolledInput extends React.Component { input = React.createRef(); getValue = () => { console.log(this.input.current.value); }; render() { return ( <input ref={this.input}/> ); } }
Więc co powinno być użyte kiedy? Powiedziałbym, że sterowane komponenty są w większości przypadków dobrym rozwiązaniem, ale są pewne wyjątki. Na przykład jednym z przypadków, w których musisz użyć niekontrolowanych komponentów w React, jest wejście typu file
, ponieważ jego wartość jest tylko do odczytu i nie można jej ustawić programowo (wymagana jest interakcja użytkownika). Ponadto uważam, że kontrolowane komponenty są łatwiejsze do odczytania i łatwiejsze w obsłudze. Przeprowadzanie walidacji dla kontrolowanych komponentów opiera się na renderowaniu, stan można zmienić i łatwo możemy wskazać, że coś jest nie tak z danymi wejściowymi (np. format lub jest pusty).
Referencje
Wspomnieliśmy już o refs
, które są specjalną funkcją, która była dostępna w komponentach klasowych, dopóki hooki nie pojawiły się w 16.8.
Referencje mogą dać programiście dostęp do komponentu React lub elementu DOM (w zależności od typu, do którego dołączamy ref) poprzez referencję. Uznaje się, że dobrą praktyką jest unikanie ich i używanie ich tylko w niezbędnych scenariuszach, ponieważ utrudniają one odczytanie kodu i przerywają przepływ danych od góry do dołu. Jednak zdarzają się przypadki, w których są one konieczne, zwłaszcza w przypadku elementów DOM (np. programowa zmiana fokusu). Kiedy dołączasz do elementu komponentu React, możesz swobodnie używać metod z tego komponentu, do którego się odnosisz. Mimo to należy unikać tej praktyki, ponieważ istnieją lepsze sposoby radzenia sobie z nią (np. podnoszenie stanu i przenoszenie funkcji do komponentów nadrzędnych).
Odniesienia mają również trzy różne sposoby, w jakie można je osiągnąć:
- Używanie literału ciągu (starszego i należy go unikać),
- Korzystając z funkcji zwrotnej, która jest ustawiana w atrybucie ref,
- Tworząc ref jako
React.createRef()
i wiążąc go z właściwością klasy i uzyskując do niej dostęp za jej pośrednictwem (pamiętaj, że referencje będą dostępne z cyklu życia componentDidMount).
Na koniec zdarzają się przypadki, w których referencje nie są przekazywane i kiedy chcesz uzyskaćdostęp do głębszego elementu referencyjnego z bieżącego komponentu (np. masz komponent <Button>
który ma wewnętrzny element DOM <input>
i właśnie teraz znajdują się w komponencie <Row>
iz tego komponentu chcesz mieć dostęp do wprowadzania funkcji DOM focus.Tutaj użyjesz forwardRef
).
Jednym z przypadków, w których referencja nie jest przekazywana, jest użycie komponentu wyższego rzędu na komponencie — przyczyna jest całkiem zrozumiała, ponieważ ref
NIE jest prop
(podobnie jak key
), więc nie jest przekazywana, więc będzie odwoływać się do HOC
zamiast do komponentu, który jest przez niego owinięty. W takim przypadku możemy użyć React.forwardRef
, który przyjmuje props i refs jako argumenty, które następnie można przypisać do prop
i przekazać do komponentu, do którego chcemy uzyskać dostęp.
function withNewReference(Component) { class Hoc extends React.Component { render() { const {forwardedRef, ...props} = this.props; return <Component ref={forwardedRef} {...props}/>; } } return React.forwardRef((props, ref) => { return <Hoc {...props} forwardedRef={ref} />; }); }
Granice błędów
Im bardziej skomplikowane stają się rzeczy, tym większe prawdopodobieństwo, że coś pójdzie nie tak. Dlatego granice błędów są częścią Reacta. Jak więc działają?
Jeśli coś pójdzie nie tak i nie ma granicy błędu jako rodzica, spowoduje to awarię całej aplikacji React. Lepiej nie wyświetlać informacji, niż wprowadzać użytkowników w błąd i wyświetlać błędne informacje, ale nie musi to oznaczać, że należy zawiesić całą aplikację i pokazywać biały ekran. Dzięki granicom błędów masz dodatkowy stopień elastyczności, z którego możesz skorzystać. Możesz użyć jednego w całej aplikacji i wyświetlić komunikat o błędzie lub użyć go w niektórych widżetach i po prostu ich nie wyświetlać lub zamiast tego wyświetlić niewielką ilość informacji.
Pamiętaj, że chodzi tylko o problemy z kodem deklaratywnym, a nie z kodem imperatywnym, który piszesz do obsługi niektórych zdarzeń lub wywołań. W tym przypadku powinieneś nadal używać standardowego podejścia try/catch .
Granice błędów to także miejsce, w którym możesz wysyłać informacje do używanego przez siebie rejestratora błędów (w metodzie cyklu życia componentDidCatch
).
class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { logToErrorLogger(error, info); } render() { if (this.state.hasError) { return <div>Help, something went wrong.</div>; } return this.props.children; } }
Komponenty wyższego rzędu
Komponenty wyższego rzędu (HOC) są często wymieniane w React i są bardzo popularnym wzorcem, którego prawdopodobnie będziesz używał (lub już to zrobiłeś). Jeśli jesteś zaznajomiony z KWR, prawdopodobnie widziałeś withNavigation, connect, withRouter
w wielu bibliotekach.
KWR to po prostu funkcje, które przyjmują komponent jako argument i zwracają nowy komponent o rozszerzonych możliwościach w porównaniu do tego, który nie zawiera opakowania KWR. Dzięki temu możesz uzyskać łatwo rozszerzalne funkcje, które wzbogacą Twoje komponenty (np. dostęp do nawigacji). KWR mogą również przybierać kilka form wywoływanych w zależności od tego, co mamy, jedynym wymaganym argumentem jest zawsze komponent, ale mogą one wymagać dodatkowych argumentów — niektóre opcje lub jak w connect
, najpierw wywołujesz funkcję z konfiguracjami, która później zwraca funkcję który pobiera komponent argumentu i zwraca KWR.
Jest kilka rzeczy, które możesz dodać i których powinieneś unikać:
- Dodaj wyświetlaną nazwę dla swojej opakowującej funkcji KWR (aby wiedzieć, że w rzeczywistości jest to KWR, zmieniając nazwę wyświetlaną komponentu KWR).
- Nie używaj KWR w metodzie renderowania — powinieneś już używać w niej ulepszonego komponentu, zamiast tworzyć tam nowy komponent KWR ze względu na jego ponowne montowanie i utratę obecnego stanu.
- Metody statyczne nie są kopiowane, więc jeśli chcesz mieć jakieś statyczne metody wewnątrz nowo utworzonego KWR, musisz je skopiować samodzielnie.
- Wspomniane
React.forwardRef
, jak wspomniano wcześniej.
export function importantHoc() { return (Component) => class extends React.Component { importantFunction = () => { console.log("Very Important Function"); }; render() { return ( <Component {...this.props} importantFunction={this.importantFunction} /> ); } }; }
Stylizacja
Stylizacja niekoniecznie jest związana z samym Reactem, ale warto o niej wspomnieć z kilku powodów.
Po pierwsze, zwykłe style CSS/inline obowiązują tutaj jak zwykle i możesz po prostu dodać nazwy klas z CSS w atrybucie className i będzie działać poprawnie. Stylizacja inline jest nieco inna niż zwykła stylizacja HTML. Łańcuch nie jest przekazywany ze stylami, ale raczej obiektami z poprawnymi wartościami dla każdego z nich. Atrybuty stylu są również camelCased, więc border-radius staje się borderRadius i tak dalej.
Wygląda na to, że React spopularyzował kilka rozwiązań, które stały się powszechne nie tylko w React, takie jak moduły CSS, które zostały niedawno zintegrowane z CRA, gdzie możesz po prostu zaimportować name.modules.css
i użyć jego klas, takich jak właściwości, do stylizacji swojego komponentu (niektóre IDE , np. WebStorm, również ma do tego funkcję Autouzupełniania, która mówi, jakie nazwy są dostępne).
Innym rozwiązaniem, które jest również popularne w React, jest CSS-in-JS (np. biblioteka emotion
). Jeszcze raz zaznaczę, że moduły CSS i emocje (lub ogólnie CSS-w-JS) nie ograniczają się do Reacta.
Hooki w React
Hooki są prawdopodobnie najbardziej oczekiwanym dodatkiem do Reacta od czasu przepisania. Czy produkt spełnia oczekiwania? Z mojej perspektywy tak, bo to naprawdę świetna funkcja. Są to zasadniczo funkcje, które otwierają nowe możliwości, takie jak:
- Pozwala na usunięcie wielu komponentów
class
, których używaliśmy tylko dlatego, że nie mogliśmy mieć np. stanu lokalnego lub ref, więc kod komponentu wygląda na łatwiejszy do odczytania. - Pozwala na użycie mniejszej ilości kodu dla tego samego efektu.
- Ułatwia myślenie i testowanie funkcji, np. za pomocą biblioteki testowej reakcji.
- Może również przyjmować parametry, a wynik jednego może być łatwo wykorzystany przez inny hak (np.
setState
zuseState
wuseEffect
). - Minifikacje są o wiele lepsze niż klasy, które bywają nieco bardziej problematyczne dla minifikatorów.
- Może usuwać KWR i renderować wzorce rekwizytów w Twojej aplikacji, które wprowadzały nowe problemy, mimo że zostały zaprojektowane do rozwiązywania innych.
- Może zostać zbudowana na zamówienie przez każdego wykwalifikowanego programistę React.
Istnieje kilka haków React, które są dołączone domyślnie. Trzy podstawowe to useState
, useEffect
i useContext
. Jest też kilka dodatkowych, np. useRef
i useMemo
, ale na razie skupimy się na podstawach.
Rzućmy okiem na useState
i użyjmy go do stworzenia przykładu prostego licznika. Jak to działa? Cóż, w zasadzie cała konstrukcja jest bardzo prosta i wygląda tak:
export function Counter() { const [counter, setCounter] = React.useState(0); return ( <div> {counter} <button onClick={() => setCounter(counter + 1)}>+</button> </div> ); };
Jest wywoływany z initialState
(wartość) i zwraca wraz z nią tablicę z dwoma elementami. Dzięki przypisaniu destrukturyzującemu tablicę możemy od razu przypisać zmienne do tych elementów. Pierwszy z nich to zawsze ostatni stan po aktualizacjach, natomiast drugi to funkcja, której użyjemy do aktualizacji wartości. Wydaje się dość proste, prawda?
Również ze względu na to, że takie komponenty były kiedyś nazywane bezstanowymi komponentami funkcjonalnymi, taka nazwa nie jest już odpowiednia, ponieważ mogą mieć taki stan, jak pokazano powyżej. Stąd nazwy komponentów klasowych i komponentów funkcyjnych wydają się być bardziej zgodne z tym, co faktycznie robią, przynajmniej od 16.8.0.
Funkcja aktualizacji (w naszym przypadku setCounter
) może być również użyta jako funkcja, która przyjmie poprzednią wartość jako argument w następującej postaci:
<button onClick={() => setCounter(prevCounter => prevCounter + 1)}>+</button> <button onClick={() => setCounter(prevCounter => prevCounter - 1)}>-</button>
Jednak w przeciwieństwie do komponentu klasy this.setState
, który wykonywał płytkie scalanie, ustawienie funkcji (w naszym przypadku setCounter
) zastępuje cały stan.

Ponadto initialState
może być również funkcją, a nie tylko zwykłą wartością. Ma to swoje zalety, ponieważ ta funkcja zostanie uruchomiona tylko podczas początkowego renderowania komponentu, a potem nie będzie już wywoływana.
const [counter, setCounter] = useState(() => calculateComplexInitialValue());
Wreszcie, jeśli zamierzamy użyć setCounter
z dokładnie taką samą wartością, jaką mieliśmy w tym samym momencie w bieżącym stanie ( counter
), komponent nie zostanie zrenderowany.
Z drugiej strony useEffect
polega na dodawaniu efektów ubocznych do naszego komponentu funkcjonalnego, czy to subskrypcji, wywołań API, timerów, czy czegokolwiek, co może nam się przydać. Każda funkcja, którą przekażemy do useEffect
zostanie uruchomiona po wyrenderowaniu i będzie to robić po każdym wyrenderowaniu, chyba że dodamy ograniczenie dotyczące tego, jakie zmiany właściwości powinny być ponownie uruchamiane jako drugi argument funkcji. Jeśli chcemy uruchomić go tylko po montowaniu i wyczyścić po odmontowaniu, wystarczy przekazać do niego pustą tablicę.
const fetchApi = async () => { const value = await fetch("https://jsonplaceholder.typicode.com/todos/1"); console.log(await value.json()); }; export function Counter() { const [counter, setCounter] = useState(0); useEffect(() => { fetchApi(); }, []); return ( <div> {counter} <button onClick={() => setCounter(prevCounter => prevCounter + 1)}>+</button> <button onClick={() => setCounter(prevCounter => prevCounter - 1)}>-</button> </div> ); };
Powyższy kod zostanie uruchomiony tylko raz z powodu pustej tablicy jako drugiego argumentu. Zasadniczo jest to coś w rodzaju componentDidMount
w takim przypadku, ale odpala się nieco później. Jeśli chcesz mieć podobny zaczep, który jest wywoływany przed malowaniem przeglądarki, użyj useLayoutEffect
, ale te aktualizacje będą stosowane synchronicznie, w przeciwieństwie do useEffect
.
useContext
wydaje się być najłatwiejszy do zrozumienia, ponieważ podaje się do jakiego kontekstu chcemy uzyskać dostęp (obiekt, który został zwrócony przez funkcję createContext
), a w zamian podaje nam wartość tego kontekstu.
const context = useContext(Context);
Na koniec, aby napisać własny hook, możesz po prostu napisać coś takiego:
function useWindowWidth() { let [windowWidth, setWindowWidth] = useState(window.innerWidth); function handleResize() { setWindowWidth(window.innerWidth); } useEffect(() => { window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return windowWidth; }
Zasadniczo używamy zwykłego haka useState
, dla którego przypisujemy szerokość okna jako wartość początkową. Następnie w useEffect,
dodajemy detektor, który będzie wyzwalał handleResize
przy każdej zmianie rozmiaru okna. Wyjaśniamy również, kiedy komponent zostanie odmontowany (spójrz na zwrot w useEffect
). Łatwo?
Uwaga: słowo użycie we wszystkich hakach jest ważne. Jest używany, ponieważ pozwala Reactowi sprawdzić, czy nie robisz czegoś złego, np. przechwytuje wywołania ze zwykłych funkcji JS.
Sprawdzanie typów
React miał własne sprawdzanie właściwości, zanim pojawiły się opcje Flow i TypeScript.
PropTypes sprawdza, czy właściwości (props) odbierane przez komponent React i czy są zgodne z tym, co mamy. Za każdym razem, gdy wystąpi inna sytuacja (np. obiekt zamiast tablicy), otrzymamy ostrzeżenie w konsoli. Należy zauważyć, że PropTypes są sprawdzane tylko w trybie deweloperskim ze względu na ich wpływ na wydajność i wspomniane ostrzeżenie konsoli.
Od React 15.5 PropTypes znajdują się w innym pakiecie, który należy zainstalować osobno. Są one deklarowane wraz z właściwościami we właściwości statycznej zwanej propTypes
(niespodzianka), łącząc je z defaultProps
, które są używane, jeśli właściwości są niezdefiniowane (jest to jedyny przypadek). DefaultProps nie są powiązane z PropTypes, ale mogą rozwiązać niektóre ostrzeżenia, które mogą pojawić się z powodu PropTypes.
Pozostałe dwie opcje to Flow i TypeScript, które są obecnie znacznie bardziej popularne (zwłaszcza TypeScript).
- TypeScript to typowany nadzbiór kodu JavaScript, opracowany przez firmę Microsoft, który może sprawdzać błędy, zanim aplikacja zostanie uruchomiona, i zapewnia doskonałą funkcjonalność autouzupełniania podczas programowania. To również znacznie poprawia refaktoryzację. Ze względu na wsparcie firmy Microsoft, która ma duże doświadczenie z pisanymi językami, jest to również dość bezpieczny wybór.
- Flow nie jest językiem, w przeciwieństwie do TypeScript. Jest to statyczny moduł sprawdzania typów dla JavaScript, więc jest bardziej podobny do narzędzia zawartego w JavaScript niż do języka. Cała idea Flow jest dość podobna do tego, co oferuje TypeScript. Umożliwia dodawanie typów, dzięki czemu jest mniej prawdopodobne, że pojawią się błędy przed uruchomieniem kodu. Podobnie jak TypeScript, Flow jest teraz obsługiwany w CRA (Create React App) od samego początku.
Osobiście uważam, że TypeScript jest szybszy (praktycznie natychmiastowy), zwłaszcza w autouzupełnianiu, który wydaje się nieco wolniejszy z Flow. Warto zauważyć, że IDE, takie jak WebStorm, z którego osobiście korzystam, wykorzystują CLI do integracji z Flow. Jednak wydaje się, że jeszcze łatwiej jest zintegrować opcjonalne użycie w plikach, gdzie po prostu dodaje // @flow
na początku pliku, aby rozpocząć sprawdzanie typu. Ponadto z tego, co mogę powiedzieć, wydaje się, że TypeScript ostatecznie wygrał bitwę z Flow — jest teraz o wiele bardziej popularny, a niektóre z najpopularniejszych bibliotek są refaktoryzowane z Flow na TypeScript.
Istnieje kilka innych opcji, o których wspomina się również w oficjalnej dokumentacji, takich jak Reason (opracowany przez Facebooka i zyskujący popularność w społeczności React), Kotlin (język opracowany przez JetBrains) i nie tylko.
Oczywiście dla programistów front-end najłatwiejszym podejściem byłoby wskoczyć i zacząć używać Flow i TypeScript, zamiast przełączać się na Kotlin lub F#. Jednak dla programistów back-end, którzy przechodzą na front-end, może być łatwiej zacząć.
Wydajność produkcji i reakcji
Najbardziej podstawową i oczywistą zmianą, którą musisz zrobić w trybie produkcyjnym, jest przejście na „produkcję” dla DefinePlugin
i dodanie UglifyJsPlugin
w przypadku Webpack. W przypadku CRA jest to tak proste, jak użycie npm run build
(który będzie uruchamiał react-scripts build
). Pamiętaj, że Webpack i CRA to nie jedyne opcje, ponieważ możesz użyć innych narzędzi do budowania, takich jak Brunch. Jest to zwykle objęte oficjalną dokumentacją, czy to oficjalną dokumentacją Reacta, czy dokumentacją konkretnego narzędzia. Aby upewnić się, że tryb jest ustawiony poprawnie, możesz skorzystać z narzędzi React Developer Tools, które wskażą Ci, jakiego rodzaju buildu używasz (produkcja vs. rozwój). Powyższe kroki sprawią, że Twoja aplikacja będzie działać bez kontroli i ostrzeżeń pochodzących z Reacta, a sam pakiet również zostanie zminimalizowany.
Jest jeszcze kilka rzeczy, które możesz zrobić dla swojej aplikacji React. Co robisz z utworzonym plikiem JS? Możesz zacząć od „bundle.js”, jeśli rozmiar jest stosunkowo mały, lub zrobić coś w stylu „dostawca + pakiet” lub może „dostawca + najmniejsza wymagana część + importuj rzeczy, gdy są potrzebne”. Jest to przydatne, gdy masz do czynienia z bardzo dużą aplikacją i nie musisz importować wszystkiego na samym początku. Należy pamiętać, że dołączenie części kodu JavaScript w głównym pakiecie, który nie jest nawet używany, po prostu zwiększy rozmiar pakietu i spowolni ładowanie aplikacji na samym początku.
Paczki dostawców mogą być przydatne, jeśli planujesz zamrażać wersje bibliotek, gdy zdasz sobie sprawę, że mogą się nie zmieniać przez długi czas (jeśli w ogóle). Ponadto większe pliki lepiej sprawdzają się przy gzipowaniu, więc korzyść z rozdzielania może czasami nie być tego warta. Zależy to od rozmiaru pliku i czasami po prostu trzeba spróbować samemu.
Dzielenie kodu
Podział kodu może pojawić się na więcej sposobów, niż sugerowano tutaj, ale skupmy się na tym, co mamy dostępne w CRA i samym React. Zasadniczo, aby podzielić kod na różne części, możemy użyć funkcji import()
, która działa dzięki Webpackowi (sam import
jest propozycją na razie w Stage 3, więc nie jest jeszcze częścią standardu językowego). Za każdym razem, gdy Webpack zobaczy import
, będzie wiedział, że musi rozpocząć dzielenie kodu na tym etapie i nie może włączyć go do głównego pakietu (kodu, który znajduje się w imporcie).
Teraz możemy połączyć go z React.lazy()
, który wymaga import()
ze ścieżką pliku zawierającą komponent, który ma być renderowany w tym miejscu. Następnie możemy użyć React.suspense()
, która wyświetli inny komponent w tym miejscu, dopóki importowany komponent nie zostanie załadowany. Można się zastanawiać; skoro importujemy pojedynczy komponent, to po co nam go potrzebować?
To nie do końca tak, ponieważ React.lazy()
pokaże komponent, który import()
, ale import()
może pobrać większy fragment niż ten pojedynczy komponent. Na przykład ten konkretny komponent może zawierać inne biblioteki, więcej kodu itp., więc jeden plik nie jest potrzebny — może to być wiele innych plików w pakiecie. Na koniec możemy umieścić to wszystko w ErrorBoundary
(kod można znaleźć w naszej sekcji dotyczącej granic błędów) , która posłuży jako rozwiązanie awaryjne, jeśli coś zawiedzie z komponentem, który chcieliśmy zaimportować (np. jeśli wystąpi błąd sieci).
import ErrorBoundary from './ErrorBoundary'; const ComponentOne = React.lazy(() => import('./ComponentOne')); function MyComponent() { return ( <ErrorBoundary> <React.Suspense fallback={<div>Loading...</div>}> <ComponentOne/> </React.Suspense> </ErrorBoundary> ); }
To podstawowy przykład, ale oczywiście możesz zrobić więcej. Możesz użyć import
i React.lazy
do dynamicznego podziału tras (np. administrator kontra zwykły użytkownik lub po prostu naprawdę duże ścieżki, które wiele wnoszą). Należy pamiętać, że React.lazy
obsługuje obecnie tylko domyślne eksporty i nie obsługuje renderowania po stronie serwera.
Działanie kodu reakcji
Jeśli chodzi o wydajność, jeśli Twoja aplikacja React działa z opóźnieniem, istnieją dwa narzędzia, które mogą pomóc w rozwiązaniu problemu.
Pierwszą z nich jest karta wydajności Chrome, która powie Ci, co dzieje się z każdym komponentem (np. montowanie, aktualizacja). Dzięki temu powinieneś być w stanie zidentyfikować, który komponent ma problemy z wydajnością, a następnie go zoptymalizować.
Inną opcją jest skorzystanie z DevTools Profiler, który stał się dostępny w React 16.5+, i dzięki współpracy z shouldComponentUpdate (lub PureComponent, co zostało wyjaśnione w pierwszej części tego samouczka), możemy poprawić wydajność niektórych krytycznych komponentów.
Oczywiście optymalne jest stosowanie podstawowych najlepszych praktyk w sieci, takich jak usuwanie niektórych zdarzeń (np. przewijanie), ostrożne korzystanie z animacji (używanie transformacji zamiast zmiany wysokości i animowania jej) i tak dalej. Stosowanie najlepszych praktyk można bardzo łatwo przeoczyć, zwłaszcza jeśli dopiero zaczynasz korzystać z Reacta.
Stan reakcji w 2019 roku i później
Gdybyśmy mieli osobiście dyskutować o przyszłości React, nie martwiłbym się zbytnio. Z mojej perspektywy React nie będzie miał problemów z utrzymaniem tronu w 2019 roku i później.
React ma tak silną pozycję, wspieraną przez liczną społeczność, że trudno będzie go zdetronizować. Społeczność React jest świetna, nie brakuje jej pomysłów, a główny zespół nieustannie pracuje nad ulepszaniem Reacta, dodawaniem nowych funkcji i naprawianiem starych problemów. React jest również wspierany przez ogromną firmę, ale problemy licencyjne zniknęły — jest teraz licencjonowany przez MIT.
Tak, jest kilka rzeczy, które powinny zostać zmienione lub ulepszone; na przykład zmniejszenie Reacta (jednym ze wspomnianych środków jest usunięcie zdarzeń syntetycznych) lub zmiana nazwy className
na class.
Oczywiście nawet te pozornie drobne zmiany mogą powodować problemy, takie jak wpływ na kompatybilność przeglądarki. Osobiście też zastanawiam się, co się stanie, gdy WebComponent zyska większą popularność, ponieważ może wzmocnić niektóre rzeczy, z którymi React często jest dziś używany. Nie wierzę, że będą całkowitym zamiennikiem, ale wierzę, że mogą się ładnie uzupełniać.
Jeśli chodzi o krótki okres, w React właśnie pojawiły się haczyki. To prawdopodobnie największa zmiana od czasu przepisania w React, ponieważ otworzą one wiele możliwości i ulepszą kolejne komponenty funkcyjne (a teraz są naprawdę podekscytowane).
Wreszcie, ponieważ to właśnie robię ostatnio, jest React Native. Dla mnie jest to świetna technologia, która zmieniła się tak bardzo w ciągu ostatnich kilku lat (brak linku w natywnych reakcjach był prawdopodobnie największym problemem dla większości ludzi i oczywiście było wiele błędów). React Native jest w trakcie przepisywania, i powinno to być zrobione w podobny sposób jak przepisanie Reacta (wszystko jest wewnętrzne, nic lub prawie nic nie powinno być zmieniane dla programistów). Renderowanie asynchroniczne, szybszy i lżejszy most między natywnym a JavaScriptem i nie tylko.
W ekosystemie React jest na co czekać, ale aktualizacje hooków (i React Native, jeśli ktoś kocha telefony komórkowe) to prawdopodobnie najważniejsze zmiany, jakie zobaczymy w 2019 roku.