Samouczek React: Jak zacząć i jak to się porównuje

Opublikowany: 2022-03-11

Front-end i w szczególności JavaScript to dziwny świat. Ilość nowych rzeczy wprowadzanych codziennie jest często wyśmiewana przez ludzi, którzy z nimi nie pracują, a wielu z nich to robi. Czasami jednak jesteśmy nieco przytłoczeni nowymi informacjami, bibliotekami i dyskusjami, a chcielibyśmy czegoś stabilnego, jak bezpieczna przystań dla statków, w której moglibyśmy zostać dłużej. Ostatnio React wydaje się być potulnym portem w morzu dynamicznej ewolucji JavaScript.

Mając to na uwadze, postanowiliśmy stworzyć ten wieloczęściowy samouczek React, aby pokazać jego możliwości i zobaczyć, jak wypada w porównaniu z Angularem i VueJS.

Ilustracja Reacta jako latarni morskiej wyraźnie widocznej nad morzem kodu JavaScript

Oczywiście React nie jest jedynym portem, z którego możemy korzystać, ale w tej chwili jest to jedno z najpopularniejszych, najbardziej stabilnych i innowacyjnych rozwiązań i choć wciąż dostaje wiele ulepszeń, są one bardziej opcją na ulepszenie niż niż konieczność funkcji.

Stan reakcji w 2019 roku

React to biblioteka widoków, do której możemy się prześledzić już w 2011 roku, kiedy na jej stronie na Facebooku pojawił się jej pierwszy prototyp, nazwany FaxJs, sam React przedstawił Jordan Walke (który jest również autorem wspomnianego prototypu) na JSConfUS na 29 maja 2013 r. i został publicznie udostępniony w serwisie GitHub 2 lipca 2013 r.

React nadal zyskiwał popularność w 2014 roku, kiedy zaczęły pojawiać się konferencje mające na celu poszerzenie społeczności i popularyzację Reacta. Jednak z mojej perspektywy rok 2015 był kamieniem milowym dla Reacta – duże firmy (np. Airbnb i Netflix) zaczęły polubić i adoptować rozwiązania Reacta. W tym samym roku pojawił się również React Native. Pomysł stojący za React Native nie był czymś zupełnie nowym, ale ciekawie było go obejrzeć, zwłaszcza że był wspierany przez Facebooka.

Kolejną dużą zmianą był Redux, implementacja Flux. Dzięki temu zarządzanie stanem stało się bardziej przystępne i łatwiejsze, co czyni tę implementację najbardziej udaną do tej pory.

Od tamtego czasu udostępniono wiele innych rzeczy, w tym narzędzia React, przepisanie podstawowego algorytmu, Fibre, zmianę wersjonowania semantycznego i tak dalej. Przechodząc do dzisiaj, jesteśmy na 16.6.3, prawdopodobnie na kilka tygodni przed udostępnieniem nowej wersji z hookami (miało to być 16.7.0, ale ta została już wydana z powodu kilku poprawek w React.lazy). React jest dobrze znany, stabilny i zbiera świetne opinie.

Ale czym jest React?

Cóż, jeśli jesteś programistą front-end i jeszcze o tym nie słyszałeś, to gratulacje są w porządku, ponieważ to nie lada wyczyn.

Żarty na bok, React to deklaratywna biblioteka widoków oparta na komponentach, która pomaga budować interfejs użytkownika. Jest to biblioteka, a nie framework, choć na początku wiele osób określiło to jako drugie.

Oczywiście, jeśli zamierzamy dodać Redux, React Router i tak dalej, zaczyna mieć wszystkie niezbędne rzeczy do stworzenia zwykłej aplikacji jednostronicowej, co może być powodem, dla którego czasami jest błędnie określany jako framework, a nie biblioteka . Jeśli już, można by argumentować, że ze wszystkimi komponentami tego środowiska razem, termin „framework” jest trochę pasujący, ale sam React jest tylko biblioteką.

Zatrzymajmy się na nomenklaturze i skupmy się na tym, co różni w React, na rzeczach, których nie mieliśmy przed jego powstaniem. Przede wszystkim, kiedy po raz pierwszy myślisz o React, myślisz o JSX, ponieważ jest to pierwsza rzecz, która pojawia się w twoim zasięgu, gdy spojrzysz na kod. JSX to rozszerzenie składni JavaScript, które nieco przypomina HTML/XML. Jeśli chodzi o Reacta i JSX, mamy kilka różnic w stosunku do HTML, np. klasa w React to className , nie ma tabindex ale tabIndex , styl akceptuje obiekty JavaScript, które mają właściwości camelCased i tak dalej.

Są pewne drobne różnice, ale każdy powinien je od razu zauważyć. Obsługa zdarzeń odbywa się poprzez np. atrybuty onChange i onClick , które można wykorzystać do dołączenia jakiejś funkcji do obsługi zdarzeń. Ponadto komponenty można później dowolnie wykorzystywać i dostosowywać za pomocą rekwizytów, więc nie ma powodu, aby kilkakrotnie pisać ten sam kod.

 import React, { Component } from 'react'; export default class App extends Component { render() { return ( <div>Hello World, {this.props.name}</div> ); } }

Jednak JSX w rzeczywistości nie jest absolutnie niezbędny w React. Możesz pisać zwykłe funkcje do tworzenia elementów bez użycia JSX. Ten sam kod, który jest powyżej, może być użyty tak jak poniżej.

 import React, { Component } from 'react'; export default class App extends Component { render() { return React.createElement( 'div', null, 'Hello World, ', this.props.name ); } }

Oczywiście nie sugeruję używania takiej składni, chociaż są przypadki, w których może się to przydać (np. chcesz wprowadzić naprawdę małą rzecz i nie chcesz zmieniać środowiska kompilacji).

Właściwie mam inny powód, dla którego pokazałem powyższy fragment. Często programiści nie rozumieją, dlaczego musimy wykonać następujące czynności:

 import React from 'react';

Fragment powinien być zrozumiały. Mimo że wyodrębniamy Component , nadal potrzebujemy Reacta, ponieważ Babel transpiluje powyżej JSX do poniżej React.createElement . Jeśli więc nie zaimportujemy Reacta, po prostu się nie powiedzie. Wspomniałem Babel, które jest narzędziem, które pomaga nam wprowadzać rzeczy, które nie są jeszcze w JavaScript (a raczej w przeglądarkach) lub są w jakiś sposób rozszerzeniami (lub innymi językami, takimi jak TypeScript, który Babel obsługuje z Babel 7). Dzięki Babel:

  • JSX zostanie przekształcony w funkcje rozumiane przez przeglądarkę.
  • Możemy używać nowych funkcji, których jeszcze nie ma w przeglądarkach (np. właściwości klas).
  • Możemy dodać funkcje, które są dostępne w nowszych przeglądarkach, ale nie ma ich w starszych, zachowując obsługę starszych przeglądarek.

Krótko mówiąc, jutro jest dzisiaj w JavaScript; jest to prawdopodobnie coś, co wymagałoby własnego artykułu. Warto wspomnieć, że import Reacta można również ominąć innymi technikami (np. wprowadzenie ProvidePlugin przez Webpack itp.), ale ze względu na ograniczoną przestrzeń tutaj tego unikniemy i założymy, że użytkownik będzie korzystał z aplikacji Create React App ( CRA) (więcej o tym narzędziu zostanie omówione później).

Drugą ważną rzeczą, o wiele ważniejszą niż sam JSX, jest to, że React opiera się na wirtualnym DOM. Krótko mówiąc, wirtualny DOM to pamięć idealnego drzewa, które jest reprezentowane przez JavaScript, który pisze programista, który jest później porównywany z rzeczywistym DOM i synchronizowany z nim w procesie zwanym rekoncyliacją.

Jak React wypada w porównaniu z Angular i Vue?

Nie lubię porównywać bibliotek, zwłaszcza gdy jesteśmy zmuszeni porównywać gruszki do jabłek (biblioteki vs. frameworki i tak dalej).

Dlatego postaram się porównać React z Angularem i Vue, używając serii krótkich pytań i odpowiedzi, które nie mają wiele wspólnego z kwestiami technicznymi, zamiast mówić coś w stylu „X jest lepszy niż Y, ponieważ używa JSX, a nie szablonów. ” Takie punkty to zazwyczaj osobiste preferencje, subiektywne wybory. Również szybkość, alokacja pamięci itp. są dość podobne w React i wszystkich jego głównych konkurentach (przychodzi mi na myśl Angular i Vue). Istnieje naprawdę dobry raport na ten temat, ale pamiętaj o tym: ogromna większość aplikacji nie wygląda jak naprawdę duże tabele, które zamieniają wiersze w tabeli 10k. Dlatego te wyniki są również czystym eksperymentem szybkości. W prawdziwym świecie w ogóle byś nie zrobił czegoś takiego.

Ilustracja React vs. Angular vs. Vue.js

Przyjrzyjmy się więc kilku pytaniom dotyczącym Reacta i tego, jak wypada na tle konkurencji:

Chcę mieć mnóstwo możliwości pracy. Jak popularny jest React?

Cóż, łatwo na to odpowiedzieć – wybierz React. Właściwie powiedziałbym, że React ma około 6-10 razy (dość duży spread, ale są portale, na których jest 1:50, a inne 1:6) więcej wakatów niż Vue i 2-4 razy więcej niż Angular. Zapotrzebowanie na ekspertów React jest duże, więc dlaczego Vue jest tak popularny na GitHubie (w rzeczywistości ma więcej gwiazdek niż React), a jednocześnie ma mniej wakatów? Nie mam pojęcia.

Chcę dużej społeczności, mnóstwa bibliotek, szybkich rozwiązań problemów, które mogą się pojawić.

Reagować. Nie szukaj dalej.

Czy jest łatwy w użyciu i sprawia, że ​​rozwój jest przyjemny?

Po raz kolejny, zgodnie z raportami State of JS za 2018 i 2017 r., zarówno React, jak i Vue cieszą się naprawdę dobrą reputacją i większość programistów twierdzi, że skorzystałaby z nich ponownie. Z drugiej strony Angular ma tendencję, z roku na rok, do wysyłania coraz większej liczby osób, które twierdzą, że nie będą z niego ponownie korzystać.

Chcę utworzyć nową aplikację jednostronicową, ale nie chcę szukać bibliotek.

To chyba jedyne miejsce, w którym Angular jest lepszym wyborem.

Żadnych wielkich korporacji. Chcę być jak najbardziej niezależny, co wybrać?

Vue – to jedyny niezależny w naszym wielkim trio. (Facebook wspiera React, podczas gdy Google jest za Angularem.)

Najłatwiejszy start i najszybsza krzywa uczenia się?

Vue/Reaguj. Skłaniam się ku Vue, ale to tylko moja osobista opinia.

Czemu? Bo nie trzeba nawet znać JSX (jest to opcjonalne) i to w zasadzie tylko HTML + CSS + JavaScript.

Samouczek React: Pierwsze kroki w Twojej pierwszej aplikacji

Samouczek React: Zrzut ekranu komunikatu o powodzeniu tworzenia aplikacji React

Najłatwiejszym sposobem na rozpoczęcie pracy z React w dzisiejszych czasach jest użycie CRA, narzędzia CLI, które tworzy dla Ciebie projekt i pomaga uniknąć wszystkich niezbędnych ustawień dla Webpack/Babel i nie tylko. Zamiast tego polegasz na tym, jak jest domyślnie skonfigurowany i co zostało w nim zawarte z biegiem czasu. Dzięki temu nie musisz przejmować się poważnymi aktualizacjami niektórych krytycznych bibliotek.

Oczywiście później możesz „wysunąć” siebie i zająć się każdym aspektem samodzielnie, uruchamiając npm run eject . To podejście ma swoje mocne strony, ponieważ możesz wzbogacić swoją aplikację o elementy, które w innym przypadku byłyby niedostępne (np. dekoratory), ale może również być źródłem bólu głowy, ponieważ wymaga wielu dodatkowych plików i znacznie więcej czasu.

Tak więc pierwszą rzeczą do zrobienia jest:

 npx create-react-app {app-name}

Następnie npm run start i jesteś gotowy do pracy.

Komponenty klasowe i funkcyjne

Powinniśmy zacząć od wyjaśnienia, czym różnią się te komponenty. Zasadniczo każdy składnik może być funkcją lub klasą . Główną różnicą między nimi jest to, że klasa 1 ma pewne cechy niedostępne w komponencie funkcyjnym: mogą mieć stan i używać refs, lifecycle itp. To jest obecny stan gry i od wersji 16.7 (lub jakkolwiek będzie nazwiemy ze względu na wspomniane zmiany), będziemy też mieli hooki, więc state i refs będą możliwe z hookami.

Istnieją dwa rodzaje składników klas: Component i PureComponent . Jedyna różnica między nimi polega na tym, że PureComponent robi płytkie porównanie właściwości i stanu — ma to swoje zalety w sytuacji, gdy nie chcesz robić renderów „zmarnowanych”, gdy komponent i jego dzieci są w dokładnie tym samym stanie po renderowaniu. To jednak tylko płytkie porównanie; jeśli chcesz zaimplementować własne porównanie (np. ponieważ przekazujesz złożone właściwości), po prostu użyj Component i shouldComponentUpdate (która domyślnie zwraca true). Od 16.6+ coś podobnego jest również dostępne z komponentami funkcyjnymi — dzięki React.memo , który jest komponentem wyższego rzędu i domyślnie zachowuje się jak PureComponent (porównanie płytkie), ale wymaga drugiego argumentu, w którym możesz przekazać własne niestandardowe porównanie właściwości .

Zgodnie z ogólną zasadą, jeśli możesz użyć komponentu funkcji (nie potrzebujesz funkcji klas), użyj go. Wkrótce, począwszy od 16.7.0, użycie komponentów klas będzie wymagane tylko ze względu na metody cyklu życia. Mam tendencję do przekonania, że ​​komponenty funkcji są bardziej przejrzyste, łatwiejsze do zrozumienia i zrozumienia.

Metody cyklu życia React

Ilustracja montażu, aktualizacji i demontażu komponentów

Konstruktor (rekwizyty)

  • Opcjonalne, zwłaszcza w przypadku tak popularnej agencji CRA, w której deklaracje pól klas dla JavaScript są dołączone domyślnie. Nie ma sensu deklarować, czy wiążesz swoje metody za pomocą funkcji strzałki w treści klasy. Podobny stan można również zainicjować jako właściwość klasy.
  • Należy używać tylko do inicjowania stanu lokalnego dla obiektów i metod wiążących w klasach ES6.

komponentDidMount()

  • Wykonuj połączenia Ajax tutaj.
  • Jeśli potrzebujesz detektorów zdarzeń, subskrypcji itp., dodaj je tutaj.
  • Możesz tutaj użyć setState (ale spowoduje to renderowanie komponentu).

componentWillUnmount()

  • Czyści wszystkie rzeczy, które wciąż trwają — np. Ajax powinien zostać przerwany, subskrypcja anulowana, liczniki czasu wyczyszczone i tak dalej.
  • Nie wywołuj setState , ponieważ jest to bezcelowe, ponieważ komponent zostanie odmontowany (i otrzymasz ostrzeżenie).

componentDidUpdate(prevProps, prevState, snapshot)

  • Dzieje się tak, gdy komponent właśnie zakończył aktualizację (nie dzieje się podczas początkowego renderowania).
  • Ma trzy parametry, które są opcjonalne do użycia (poprzednie właściwości, poprzedni stan i migawka, która pojawi się tylko wtedy, gdy komponent zaimplementuje getSnapshotBeforeUpdate ).
  • Dzieje się tak tylko wtedy, gdy shouldComponentUpdate zwraca wartość true.
  • Jeśli użyjesz tutaj setState , powinieneś go strzec, albo wylądujesz w nieskończonej pętli.

shouldComponentUpdate(nextProps, nextState)

  • Tylko do optymalizacji wydajności.
  • Jeśli zwróci false, render NIE zostanie wywołany.
  • Zamiast tego można użyć PureComponent , jeśli nadpisane SCO jest tylko płytkim porównaniem właściwości/stanów.

pobierzSnapshotBeforeUpdate()

  • Może służyć do przechowywania niektórych informacji o bieżącym DOM, np. bieżącej pozycji przewijania, które później mogą być ponownie użyte w componentDidUpdate do przywrócenia pozycji przewijania.

componentDidCatch(błąd, informacja)

  • Miejsce, w którym powinny wystąpić błędy logowania.
  • Może wywołać setState , ale w przyszłych wydaniach zostanie odrzucona na rzecz statycznej metody getDerivedStateFromError(error) , która będzie aktualizować stan poprzez zwrócenie wartości aktualizującej stan.

Istnieją dwie dodatkowe metody, które są statyczne i zostały wymienione w innych wyjaśnieniach

statyczne getDerivedStateFromError(błąd)

  • Informacje o błędach są dostępne tutaj.
  • Powinna zwrócić wartość obiektu, która zaktualizuje stan, który może być użyty do obsługi błędów (poprzez wyświetlenie czegoś).
  • Ponieważ jest statyczny, nie ma dostępu do samej instancji komponentu.

static getSnapshotBeforeUpdate(rekwizyty, stan)

  • Powinien być używany w przypadkach, gdy właściwości zmieniają się w czasie — na przykład, zgodnie z dokumentacją React, może być przydatny w przypadku komponentu przejściowego.
  • Ponieważ jest statyczny, nie ma dostępu do samej instancji komponentu.

Uwaga, na dzień dzisiejszy dostępnych jest jeszcze kilka metod, ale powinny one zostać usunięte w React 17.0, dlatego nie zostały tutaj wymienione.

Państwo a rekwizyty

Zacznijmy od Rekwizytów , ponieważ są one łatwiejsze i szybsze do wyjaśnienia. Rekwizyty to właściwości, które są przekazywane do komponentu, które później mogą być ponownie użyte w nim do wyświetlania informacji / logiki biznesowej i tym podobnych.

 import React, { Component } from 'react'; export default class App extends Component { render() { return ( <div> <HelloWorld name="Someone :)"/> </div> ); } } const HelloWorld = (props) => <div>Hello {props.name}</div>

W powyższym przykładzie name jest propozycją. Rekwizyty są elementami tylko do odczytu i nie można ich zmieniać bezpośrednio w komponentach podrzędnych. Jest też jedna zła praktyka, którą ludzie często stosują, a mianowicie kopiowanie rekwizytów do państwa i późniejsze operowanie na państwie. Oczywiście są przypadki, w których chcesz zrobić coś takiego jak „stan początkowy, który zaktualizuje komponent nadrzędny po przesłaniu”, ale jest to rzadsze — w takim scenariuszu podawanie stanu początkowego może mieć sens. Ponadto do komponentów podrzędnych można przekazywać nie tylko właściwości, takie jak ciągi, ale także liczby, obiekty, funkcje itp.

Props ma jeszcze jedną użyteczną rzecz, nazywaną defaultProps , pole statyczne, które może powiedzieć, jakie są domyślne właściwości komponentu (na przykład, gdy nie są przekazywane do komponentu).

W przypadku „lifting state up”, gdzie jeden komponent (rodzic) ma stan, który jest później ponownie używany przez jego dzieci (np. jedno dziecko go wyświetla, a drugie umożliwia edycję), to musimy przekazać funkcję do dziecka z parent, co pozwala nam aktualizować stan lokalny rodzica.

Z drugiej strony State jest stanem lokalnym, który można modyfikować, ale pośrednio za pomocą this.setState . Jeśli ktoś zmutowałby stan bezpośrednio, komponent nie będzie świadomy zmiany i nie zostanie renderowany w celu odzwierciedlenia wspomnianych zmian stanu.

SetState to metoda zmiany lokalnego obiektu stanu (poprzez wykonanie płytkiego scalenia), a następnie komponent odpowiada na to, renderując się. Należy pamiętać, że po setState właściwość this.state nie będzie odzwierciedlać zmian wymienionych w funkcji od razu (ma charakter asynchroniczny), ponieważ kilka wystąpień setState może być połączonych wsadowo ze względu na optymalizację. Ma kilka sposobów na wywołanie, gdzie jedna z tych możliwości pozwala nam coś zrobić z komponentem zaraz po aktualizacji stanu:

  • setState({value: '5'})
  • setState((state, props) => ({value: state.name + “'s”}))
  • setState([object / function like above], () => {}) – ta forma pozwala nam dołączyć callback , który zostanie wywołany, gdy stan będzie odzwierciedlał dane, które chcieliśmy mieć (w pierwszym argumencie).
 import React, { Component } from 'react'; export default class App extends Component { state = { name: 'Someone :)' } onClick = () => this.setState({ name: 'You' }) render() { return ( <div> <HelloWorld name={this.state.name} onClick={this.onClick}/> </div> ); } } const HelloWorld = (props) => <div onClick={props.onClick}>Hello {props.name}</div>

Kontekst reakcji

React niedawno ustabilizował Context API (który był w React przez jakiś czas, ale był funkcją eksperymentalną, mimo że był powszechnie używany przez niektóre z najpopularniejszych bibliotek, takich jak Redux), co pomaga nam rozwiązać jeden problem: wiercenie rekwizytów. Krótko mówiąc, drążenie rekwizytów to sposób na przekazywanie rekwizytów głęboko w strukturze — np. może to być jakiś motyw dla komponentów, lokalizacja dla określonego języka, informacje o użytkowniku i tak dalej. Przed Context (a raczej zanim stał się nieeksperymentalny), był on drążony poprzez przekazywanie w sposób rekurencyjny od rodzica do dziecka do ostatniego liścia (oczywiście był Redux, który również mógł rozwiązać problem). Należy pamiętać, że ta funkcja rozwiązuje TYLKO wiercenie rekwizytów i nie zastępuje rzeczy takich jak Redux lub Mobx. Oczywiście, jeśli używałeś biblioteki zarządzania stanem tylko do tego, możesz ją dowolnie zastąpić.

Zawijanie

To kończy pierwszą część naszego samouczka React. W nadchodzących artykułach mamy nadzieję poruszyć bardziej zaawansowane tematy, od stylizacji i typów sprawdzania po wdrażanie produkcyjne i optymalizację wydajności.

Powiązane: Utrzymuj kontrolę: przewodnik po pakietach internetowych i reakcjach, Pt. 1