od Podstaw
5 godz. 59 min · ReactJS · Full-stack i Programowanie
Michał JabłońskiReact przeszedł długą ścieżkę rozwoju i część z jego funkcjonalności nie są już powszechnie używane. Dlatego w tym kursie skupimy się na najnowszych technikach pracy z biblioteką - poznasz współczesne podejście do budowania komponentów z wykorzystaniem hooks (useState, useEffect), zrozumiesz zasady kompozycji i zarządzania stanem aplikacji. Pokażemy Ci też jak efektywnie korzystać z narzędzi deweloperskich, debugować kod i wdrażać aplikacje na produkcję z użyciem współczesnych platform jak Vercel.
Hooki to fundament nowoczesnego Reacta, który całkowicie zmienił sposób tworzenia komponentów. W kursie nauczysz się efektywnie zarządzać stanem aplikacji używając useState, wykorzystywać useEffect do operacji lifecycle i side-effects, oraz poznasz reguły korzystania z hooków. Wszystko to przećwiczysz w praktycznych zadaniach, takich jak implementacja filtrowania listy elementów, gdzie zastosujesz zdobytą wiedzę w realnym scenariuszu.
Obsługa formularzy to nieodłączny element każdej aplikacji webowej. Pokażemy Ci jak kontrolować wartości pól input, wykorzystać popularną bibliotekę Formik do zarządzania złożonymi formularzami oraz implementować walidację danych. Wiedza ta zostanie utrwalona poprzez praktyczne zadanie, w którym rozwiniesz formularz o dodatkowe pola i zastosujesz poznane techniki w rzeczywistym przypadku użycia.
Większość aplikacji wymaga komunikacji z serwerem. Nauczysz się jak poprawnie wykonywać operacje asynchroniczne w komponentach React, obsługiwać stany ładowania i błędów, oraz efektywnie korzystać z klienta HTTP do zapytań AJAX. Zaczniesz od pracy z przygotowanym mockiem API, by następnie przejść do prawdziwej integracji z back-endem. W praktycznym zadaniu zaimplementujesz pełny przepływ danych - od pobrania, przez wyświetlenie, aż po wysłanie na serwer.
Poza budową aplikacji React, w kursie znajdziesz także moduł poświęcony wdrażaniu aplikacji na produkcję. Poznasz prawidłową konfigurację serwera produkcyjnego dla architektury SPA, nauczysz się zarządzać zmiennymi środowiskowymi poprzez pliki .env oraz przeprowadzisz deployment na platformie Vercel. Dzięki temu Twoja aplikacja będzie nie tylko działać lokalnie, ale także będzie gotowa do użycia przez realnych użytkowników w internecie.
Nowoczesny React stworzyliśmy z myślą o osobach, które chcą nauczyć się Reacta i jednocześnie znają JavaScript. Niezależnie od tego, czy React jest Twoim pierwszym frameworkiem, czy masz już doświadczenie w pracy np. ze Svelte czy Vue, ten materiał jest dla Ciebie. Wskazane jest również posiadanie ogólnej wiedzy na temat tworzenia interfejsów z HTML i CSS oraz obsługi narzędzi takich jak Git czy podstawy pracy z terminalem.
Gdybyśmy dostali takie zadanie, że mamy zasalektować Johna po dwóch sekundach i
mamy to zrobić w kodzie, Czyli chcemy, żeby coś takiego wydarzyło
się, ale od strony kodowej.
Po dwóch sekundach moglibyśmy pójść sobie dość naiwnie robiąc
po prostu set timeout i ten set timeout miałby nam odliczyć dwie sekundy.
W sumie jest to coś, co będzie absolutnie potrzebne do wykonania tego zadania, więc
ten set timeout jest bardzo dobrym pomysłem.
I zobaczmy sobie tutaj po prostu weźmiemy sobie set SelectedNames, ale name, który
chcemy selectować to będzie po prostu join.
Na razie pomińmy całą tą logikę z handle select.
Chcemy sobie po prostu pójść quick win Tak i wygląda to poprawnie.
Jeśli podejdziemy sobie tutaj F12, otworzymy narzędzia deweloperskie.
W konsoli nie ma żadnych błędów, wszystko wygląda na poprawnie.
Jednak jeśli dopiszemy sobie tutaj consoleloga
i zobaczymy kiedy updejtuje się nasz komponent, to okaże się, że jeśli
odświeżymy ten widok i zobaczymy sobie jak to działa, okaże się, że
dostajemy tutaj 4, 6, 8.
Wiemy o tym, że to wyskoczy nam dwa razy, ale nie spodziewaliśmy się, że
Settimeout zadziała jak z Sett Interval.
Zauważ, że tutaj co dwie sekundy znowu i znowu mamy updated.
Ciekawe, czy zatrzymując na chwilę to wideo i zastanawiając się dlaczego
dojdziesz do tego, czemu tak się dzieje?
Czemu ten kod nie do końca jest poprawny?
Okej, rozwiązanie naszego zadania jest tutaj.
Używamy setSelectedNames.
Tak jak Ci mówiłem za każdym jednym razem, jeżeli korzystasz z Hooka State i
zaktualizujesz stan, ten cały kod wywoła się ponownie.
Co za tym idzie, Settimeout wywołuje się owszem jednorazowo
w momencie, gdy komponent osadza się na domie, ale później, w momencie, w którym
uruchamiamy setSelectedNames zmieniamy stan, więc render się wykonuje i ponownie
wszystko razem z tym Settimeout'em zostaje wykonane.
W takim układzie Settimeout będzie działał jak Sett Interval, dlatego, że za każdym
razem jak mamy setSelectedNames zaktualizujemy to.
Więc nie do końca jest to poprawnie, nie do końca tak jakbyśmy chcieli.
Jest taki hook, który nazywa się Use effect.
I ten właśnie use effect posłuży nam do tego, żeby rozwiązać ten problem.
Do Use Effect wrzucamy callback i tak będzie to wyglądało, że przesuniemy ten
set timeout tutaj, jeżeli zrobimy to tylko w ten sposób.
Tak naprawdę nic nie zmieniliśmy, a updated będzie wykonywane.
Jak widzisz tutaj jedyne cośmy osiągnęli to to, że jak gdyby use effect
nie wywołuje się dwa razy.
Czyli wykonanie czegoś w efekcie sprawia, że nie zostaje wykonana ta reguła ze
strictmode i jak gdyby widzimy, że to się jednorazowo tylko aktualizuje,
ale efekt jest ten sam.
Żeby skorzystać z Life style Metody.
Można tak to nazwać, można tak to ująć.
Ten efekt Możemy dostarczyć do niego tablice dependencies jako drugi argument
i wtedy zupełnie inaczej on działa.
On wykonał się jednorazowo.
Czyli gdybyśmy odświeżyli tą stronę, żeby sobie zobaczyć co tutaj się dzieje, a
updated wykona się jednorazowo i później za każdym jednym kolejnym update'em,
jak gdyby nie mamy tego updated.
Dlatego, że pusta tablica dependencies oznacza, że chcemy tylko
jednorazowo ustalić use effect.
Jednak zwróć uwagę, że tutaj Sline zwraca nam uwagę, że korzystamy z selected names,
a to jest dependency i mamy missing dependency.
I on ma rację w sensie takim, że to selected names powinno być tutaj
wymienione dlatego, że korzystamy z zależności zewnętrznej.
Jeżeli ta zależność zewnętrzna się zmieni, moglibyśmy chcieć jeszcze
raz zrobić use effect.
Zauważ, że w tym momencie wracamy do punktu wyjścia.
To znaczy use effect będzie się aktualizował za każdym jednym razem.
Dlatego, że w tablicy dependencies podaliśmy mu kawałek stanu, a ten stan
aktualizujemy w środku samego tego useffect.
W takim wypadku koło się zamyka, dlatego, że w momencie aktualizacji
tego useffect nam się wykona.
Taki mamy kontrakt.
A ponieważ my aktualizujemy SelectedNames właśnie używając set
selectednames, czyli tego etc.
To Useffect sam będzie obserwował to dependency i ponownie nam
się wykona właśnie tutaj.
Co zrobić w takim wypadku, żeby z jednej strony zadowolić snintera, czyli nie
popełnić tego błędu, że korzystamy z jakiegoś dependency, aktualizujemy to, a z
drugiej strony chcemy to wywołać tylko i wyłącznie jednorazowo, czyli chcielibyśmy
pozostać przy tej pustej tablicy dependencies.
Tak, żeby Józefek działał w ten sposób, że właśnie tylko wykona nam
się raz dla tego komponentu.
Żeby takie coś osiągnąć musimy sobie przypomnieć.
W JSX robiliśmy taki SimpleButton i zauważ, że na tym sampleButton
wykorzystywaliśmy troszeczkę inne podejście do Etc seter zamiast
korzystać z zewnętrznych zależności.
Czyli jeśli potraktujemy sobie ten count jako zewnętrzna zależność tego kodu, który
mamy tutaj i tego callback, który jest tutaj.
Zauważ, że Count jest w Outer Scope, to setCount kompletnie z tego nie korzysta.
I dokładnie do takiej sytuacji możemy doprowadzić tutaj.
Czyli zamiast korzystać właśnie z tej zewnętrznej zależności z Outer Scope,
zamiast korzystać z Selected names wiemy o tym, że to selected names.
Skrótowo zapiszmy sobie to jako SN.
Celowo robię to z inną nazwą, być może nie do końca trafną, bo dość skrótową.
Natomiast zauważ, że idea jest taka, żeby tego nie pomylić z tym outer
skopem, który mamy tutaj.
Chcę, żebyś zobaczył, że to SN, które mamy tu, to jest ta sama wartość jak selected
names w aktualnym stanie, dlatego, że możemy sobie updateować set selected
names używając właśnie callback.
Wtedy dostaniemy aktualną wartość selected names.
Ale uwaga dostaniemy tą aktualną wartość w postaci parametru, który dostajemy z
callbacka, więc to nie jest zewnętrzna zależność.
SetSelectedNames Zobacz, że już nie mamy tego błędu.
Pozbyliśmy się tego błędu, a z drugiej strony nasz kod działa poprawnie.
Gdybyśmy go teraz odświeżyli, zobaczymy tylko dwukrotnie, dlatego, że ten strict
mode wykona się dwa razy za pierwszym razem, natomiast za każdym kolejnym, gdyby
Useffect wykonywał się ponownie ponownie tutaj, mielibyśmy tylko jedną
aktualizację, tak jak widziałeś wcześniej.
W tym układzie mamy rozwiązane zadanie i to jest prawidłowo rozwiązane zadanie.
Najważniejsza rzecz, którą chcę, żebyś wyciągnął z tego przykładu, to jest
oczywiście to, że Use effect, jego działanie, jego sposób działania
zależy od tej tablicy dependencies.
Jeśli tablica dependencies jest pusta.
Wtedy use effect wykona się jednorazowo.
Z drugiej strony tablica nie może być pusta, jeśli faktycznie korzysta
z czegoś, co jest w Outer Scope.
Najgorzej byłoby chyba, gdybyśmy użyli handle select dlatego, że jeżeli
odpalilibyśmy Handle Select z Johnem, okazuje się, że handle select
też jest zewnętrzną zależnością.
Czyli niezależnie od tego, czy masz coś ze stanu czy spoza stanu, musi to być
jak gdyby w tablicy dependencies.
I teraz w tablicy dependencies handle select umieszczenie powoduje, że
nie do końca to działa poprawnie.
Czyli wrócilibyśmy do punktu wyjścia dlatego, że handle select zmieni
się za każdym jednym razem.
I taką mamy informację od Clinta, że musielibyśmy tutaj użyć jeszcze innego
hooka, którym jest use callback.
Z kolei gdybyśmy opakowali to w use callback jako hooka, który spowodowałby,
że handle select się nie zmienia, musielibyśmy pozbyć się tych zależności
tutaj, czyli selected names i selected names.
Musielibyśmy to przepisać właśnie na taką aktualizację, gdyż w innym przypadku
mielibyśmy znowu to koło, że jeżeli use callback, który też będzie miał swoje
dependencies, będzie zależał od czegoś jeszcze, czyli set selected names to w
momencie update'u setSelectedNames updateuje się juz callback.
Co za tym idzie wykona się Use effect.
Innymi słowy to jest bardziej skomplikowany przykład i na
razie nie musimy go robić.
Na razie skupmy się na tym, co jest tutaj.
Zależy mi na tym, żebyśmy zrozumieli, że jeżeli użyjemy pustej tablicy, będziemy
mieli to wykonane jednorazowo, w momencie, gdy ten komponent umiejscowi się tutaj.
Co więcej, Use Effect jako lifecycle method może wykonywać się
niezależnie kilka razy.
To znaczy, możesz mieć taką sytuację, że tutaj mamy jeden use effect, który robi
side effect, czyli zsynchronizuje stan naszego komponentu w tym miejscu za
pierwszym razem, a za drugim razem mamy zupełnie inny callback,
zupełnie inny use effect.
Jest jeszcze jedna sprawa, o którą musimy zadbać.
Ten effect potencjalnie mógłby być niebezpieczny w momencie, w
którym montujemy komponent.
Wyobraź sobie, że odmontowujemy komponent i wtedy set selected names
nie ma żadnego znaczenia.
W sensie takim, że dostaniemy wtedy tak zwanego memory like'a, Ponieważ
dwie sekundy dalej się odliczą.
Set selected names dalej się wykona, ale komponent nie będzie już z nami.
To znaczy. Wyobraźmy sobie sytuację, w której np.
Przelatujemy się na inną stronę, nie mamy jeszcze tego routingu wpięty, ale wtedy
ten komponent z list of people po prostu zniknie.
Co by było, gdyby dalej odliczał te dwie sekundy?
Cóż, mielibyśmy tak zwanego memory linka?
To znaczy dalej ten kod by się wykonywał po dwóch sekundach, ale
komponentu już by nie było.
Co robić w takich sytuacjach?
Use Effect ma tak zwaną clean up function, którą zwraca właśnie w tym
callbacku, który mamy tutaj.
To znaczy my możemy ją dopisać jako zwrotka i wtedy wyczyścić sobie ten set
timeout, czyli naprawić to, co mielibyśmy w tym miejscu odliczać dalej.
Po prostu wystarczy, że będziemy mieli timer ID.
I teraz standardowo w JavaScripcie mamy coś takiego jak clean time out i to
clear time out przyjmuje timer ID.
Czyli mamy clear time out.
I w tym momencie jak gdyby to będzie clean up.
Jak to działa w tym konkretnym przypadku?
Just Effect wywołuje się jednorazowo w momencie, gdy komponent nam się
zainicjuje, będziemy mieli tylko jeden raz, więc ten clean up będzie w momencie,
w którym na przykład komponentu już z nami zabraknie, czyli w momencie, w którym jak
gdyby komponent zostaje odmontowany z dom.
Ten clean up function akurat się wywoła.
Nie musi to koniecznie tak działać, ponieważ use effect w momencie, w którym
mielibyśmy dependencies, czyli na przykład to selected names.
Tak jak mieliśmy wcześniej, stwierdzaliśmy już, że taki zapis akurat
nie ma sensu, Ale gdyby się tak wydarzyło, że będziemy mieli taki ciąg przyczynowo
skutkowy, że ten use effect ma się wykonać za każdym razem jak nasze dependencies się
zmienią, pamiętaj, że to dependencies to może być stan,
to mogą być funkcje, z których korzystamy, to mogą być również propsy,
czyli również props.
Możemy mieć tutaj dependencies i chcieć zrobić aktualizację efektu.
To wtedy jak gdyby ten clean up będzie za każdym razem, kiedy ma być
uruchomiony następny Just effect? Co to znaczy?
Wyobraźmy sobie, że zależymy od Selected names.
Selected names się zmienia, więc timer zaczyna odliczać dwie sekundy.
Ale uwaga w tym czasie selected names z jakiegoś zewnętrznego źródła
znowu nam się zmienia.
I w takim układzie, skoro zmienia się selected names, znowu wywołuje się
juz effect razem z tym callbackiem.
Ale zanim wywoła się najpierw tego poprzedniego callbacka, który mieliśmy,
wywoła się ten clean up function i dopiero później po tym clean up function wywoła
nam się znowu use effect i będziemy mieli taki ciąg przyczynowo skutkowy.
Przywróćmy sobie to do stanu takiego, jakiego byśmy chcieli.
Czyli jakby mamy tą funkcjonalność, że za każdym razem gdy renderuje się ten widok
to John zostanie selectowany po dwóch sekundach.
Jeśli sobie to oczywiście zakomentujesz, jak gdyby ta logika nie
będzie miała miejsca.
Natomiast możemy sobie to na razie w ten sposób zostawić, tak, żeby
przećwiczyć sobie use effect.