Main

React - kurs podstaw w 2h krok po kroku!

⭐ https://zrozumiecreact.pl/ - Sprawdź nasz kurs React! ⭐ 👉 Zapisz się na newsletter: https://zaczynamyprogramowac.pl 👈 🎤 Discord: https://discord.gg/q88RUeTHbU 🎤 🔥 Zapisz się do grupy na FB: https://www.facebook.com/groups/zaczynamy.programowac/ 🔥 [00:00] #0 - Intro [09:29] #1 - Konfiguracja VSC https://www.youtube.com/shorts/Db9CZwuVows?feature=share [12:25] #2 - Stawianie projektu za pomocą Vite [15:49] #3 - JSX, React i ReactDOM https://youtu.be/a_SR7601eVU [26:08] #5 - Elementy Reactowe [28:44] #6 - Możliwości JSX https://youtu.be/OobPUQ6_UTk [43:33] #7 - Fragment [46:21] #8 - Komponenty [53:06] #9 - Props [01:04:45] #10 - Exportowanie komponentów [01:10:28] #11 - App Component https://youtu.be/a_SR7601eVU [01:14:17] #12 - Listy i tablice https://youtu.be/u3S-2HYFjVg [01:20:44] #13 - Conditional rendering https://youtu.be/vVOJ8cuFSLY [01:23:55] #14 - Event Handlery [01:32:28] #15 - Stan https://youtu.be/1o2jlscePis https://youtu.be/bygf54HllIQ [01:45:54] #16 - Formularze [01:57:27] #17 - Komunikacja komponentów https://youtu.be/bygf54HllIQ https://youtu.be/-mbiJ2it-5M [02:05:49] #18 - Stylowanie [02:14:42] #19 - Dynamiczne klasy [02:18:21] #20 - Build i deploy na Netlify [02:20:40] #21 - Co dalej? Kod końcowy: https://github.com/Jak-zaczac-programowac/kurs-podstaw-react ⭐ https://zrozumiecreact.pl/ - Sprawdź nasz kurs React! ⭐ Filip Mamcarczyk Kacper Sokołowski

Jak zacząć programować?

2 weeks ago

Cześć, witaj w kursie Podstaw Reacta. Jak ten film będzie wyglądał? Zaczniemy od omówienia wymagań i zagadnień, które musisz już znać, żeby w ogóle zrozumieć co dzieje się w React'cie. Potem wyjaśnię czym jest React i opowiem dlaczego warto się go uczyć. Następnie przejdziemy już do praktycznej części kursu. Będziemy budować prostą aplikację, a ja krok po kroku przeprowadzę cię przez podstawy działania Reacta. Dzięki temu dowiesz się z czym się go je i zdobędziesz solidne podstawy do dalszej nau
ki. Jeśli nie lubisz wstępów i chcesz od razu przejść do kodowania, to możesz przewinąć film do tego fragmentu. Serdecznie zapraszam. W internecie znajduje się mnóstwo materiałów dotyczących Reacta, ale niestety większość z nich jest już bardzo przestarzała i na początku ciężko odnaleźć się w gąszczu tych wszystkich tutoriali. Przykładowo wiele filmów dotyczących Reacta na YouTubie ma już kilka lat i prezentuje mechaniki takie jak komponenty klasowe i Create React App, które już odchodzą do lamu
sa. Dlatego bardzo zależało nam na tym, żeby nagrać aktualny kurs wprowadzający do Reacta. Więc jeśli chcesz postawić pierwsze kroki w Reactie, poznać jego podstawy i zdobyć aktualną wiedzę, to jesteś w dobrym miejscu. W tym tutorialu dowiesz się czym jest React, ReactDOM i JSX. Nauczysz się stawiać Reactowy projekt, tworzyć komponenty i komunikować je ze sobą. Oprócz tego pokażę Ci też jak stosować event handlery i hook useState. Na koniec zobaczysz jak ostylować aplikację i jak zdeployować ją
na Netlify. Zanim zaczniemy, porozmawiajmy o tym co musisz już umieć, żeby przystąpić do nauki Reacta. Jednym z najczęstszych błędów popełnianych przez osoby stawiające swoje pierwsze kroki we frontendzie jest rozpoczynanie nauki Reacta bez dokładnego przerobienia podstaw frontendu. Jeśli dopiero zaczynasz przygodę z frontendem, to jeszcze nie czas na naukę Reacta. Nie jest to specyficzne dla naszego kursu. Po prostu próba nauczenia się Reacta bez znajomości podstaw ma mniej więcej tyle sensu co
próba nauki gry w hokeja bez nauczenia się jeżdżenia na łyżwach. Co więc musisz już umieć? Przede wszystkim HTML. Umiesz budować strony, a tworzenie list czy formularzy nie stanowi dla Ciebie problemu. CSS. Rozumiesz różnicę pomiędzy inline styles a zewnętrznym arkuszem stylów. Specificity nie jest Ci obce, no i potrafisz wycentrować diva. A teraz najważniejsze wymaganie, czyli Javascript. Rozumiesz ogólne filary programowania takie jak zmienne funkcje, pętle, ify i znasz zagadnienia specyficzn
e dla Javascript takie jak drzewo dom, eventy czy asynchroniczność. A dodatkowo oprócz wiedzy czysto frontendowej ogarniasz podstawy terminala, npm-a, rozumiesz różnicę pomiędzy backendem i frontendem i wiesz do czego służy funkcja fetch. Jeśli któreś z tych zagadnień sprawia problem, to serio, na naukę Reacta przyjdzie jeszcze czas, a na razie lepiej jest skupić się na podstawach. W opisie znajdziesz link do playlist, w których zajmujemy się tymi podstawowymi tematami, więc możesz na spokojnie
przez nie przejść i dopiero wtedy wrócić do tego filmu. Jeśli jednak znasz już podstawy, to nic nie stoi na przeszkodzie, żeby przejść do nauki Reacta. Zacznijmy od wyjaśnienia czym w ogóle jest React. Cóż, React to w praktyce i dużym uproszczeniu zbiór funkcji javascriptowych, dzięki którym możemy szybciej i wygodniej tworzyć aplikacje. Jako, że React to zwykły kod JS, to możemy go najwzwyczajniej w świecie dodać do naszej strony, albo pobrać w naszym projekcie jako paczkę npm-ową i zacząć używ
ać tak jak wszystkie inne standardowe funkcje JS-owe. Zobaczymy jak to zrobić już za parę minut. Tymczasem skupmy się na tym, dlaczego warto uczyć się Reacta. Według State of JS, React to od wielu lat najbardziej popularne frontendowe narzędzie. Na Just Join IT są 2363 oferty wymagające javascriptu. Warto zwrócić uwagę, że są to oferty zarówno frontendowe, jak i backendowe. Natomiast ofert wymagających Reacta jest aż 2048. Tutaj nie sposób nie rzucić starego informatycznego suchara. Cóż za piękn
a, okrągła liczba. Pokazuje to jak wielką część rynku jeśli chodzi o technologię zajmuje React. Co więcej, w większości materiałów tłumaczących bardziej zaawansowane zagadnienia z frontendem, takie jak np. architektura aplikacji, to właśnie React jest wykorzystywany do przedstawienia przykładów i obrazowania rozwiązań. W związku z powyższym, można łatwo stwierdzić, że obecnie znajomość Reacta to już nie tylko dodatek do CV. Znajomość Reacta to konieczność na drodze do rozwijania się jako fronten
d developer. Ale co sprawia, że React jest tak popularny? Wyobraźmy sobie prostą aplikację internetową. Kod JS i HTML potrzebny do stworzenia takiej aplikacji wygląda następująco. Tymczasem kod potrzebny do stworzenia takiej aplikacji w Reactie wygląda tak. Pomimo tego, że jest to bardzo prosta aplikacja, to gołym okiem widać, że kod reactowy jest krótszy. Wraz ze wzrostem aplikacji i liczby jej funkcjonalności, różnica pomiędzy tworzeniem aplikacji w czystym JS, a w Reactie zwiększa się na korz
yść Reacta. Jeśli React to dla ciebie nowość, kompletnie nie przejmuj się kodem po prawej. Już za chwilę przejdziemy do tłumaczenia Reacta. Na razie zapamiętajmy po prostu, że pierwszym powodem, dla którego warto używać Reacta jest fakt, że wraz ze wzrostem aplikacji, React pozwala nam rozwijać aplikacje w dużo szybszy i wygodniejszy sposób. Oczywiście w małych aplikacjach różnica pomiędzy Reactem, a zwykłym JSem jest znikoma. Ale bądźmy szczerzy, w codziennej pracy bardzo rzadko tworzymy małe,
proste aplikacje. Kod pisany w Reactie pozwala na deklaratywne tworzenie części interfejsu. Pomyślmy o wizycie w restauracji. Kiedy zamawiasz posiłek, nie mówisz do kelnera, proszę wyciągnąć talerze, wyciągnąć nóż, wyciągnąć sałatę i pomidory, pokroić nożem sałaty i pomidory, położyć je na talerzu i mi przynieść. Mówimy po prostu, poproszę o sałatkę z pomidorem. I React działa podobnie. Wydajemy mu krótkie polecenia, opisujemy co chcemy dostać, a on załatwia wiele spraw za nas. Na razie brzmi to
mocno abstrakcyjnie, ale z biegiem czasu nabierze więcej sensu. Drugim powodem, dla którego warto używać Reacta jest fakt, że w wielu przypadkach optymalizuje on działanie naszej aplikacji i znacząco poprawia jej wydajność. Ta różnica ponownie jest szczególnie widoczna przy większych aplikacjach. Zobaczmy co stanie się, gdy w naszej aplikacji dodamy 10 tysięcy elementów i spróbujemy usunąć jeden z nich. W aplikacji po lewej, napisanej w zwykłym JS, dostrzegalny jest długi lag, natomiast aplikac
ja po prawej wyświetla zmianę praktycznie natychmiastowo. Oczywiście w zwykłym JS również jesteśmy w stanie stworzyć zoptymalizowane i szybkie aplikacje, ale React bardzo ułatwia cały ten proces. Kolejnym, trzecim powodem, dla którego warto nauczyć się Reacta jest fakt, że zapewnia on elastyczność i reużywalność tworzonych komponentów. Co to znaczy? Wyobraźmy sobie, że tworzymy stronę, na której korzystamy z powtarzającego się batona. Z biegiem czasu dodajemy więcej sekcji i elementów, w których
ten baton się pojawia. Stosując podstawowe narzędzie takie jak HTML, CSS i JavaScript, bardzo często decydujemy się po prostu na tworzenie takiego batona za każdym razem od początku. Oznacza to, że jeżeli będziemy musieli przykładowo zmienić treść naszego batona, to prawdopodobnie będziemy musieli zrobić to kilkukrotnie, we wszystkich miejscach, w których występuje. React zachęca nas do korzystania z komponentów. Komponenty to podstawowe bloki budulcowe aplikacji, które zawierają w sobie wygląd
, logikę i style danych elementów. Przykładem komponentu może być właśnie specyficzny baton z konkretnymi stylami. Komponenty definiujemy raz za pomocą specjalnych przepisów, a następnie używamy tego przepisu w miejscach, w których jest potrzebny. W dużym uproszczeniu możemy o tym pomyśleć jak o tworzeniu swoich własnych tagów HTML. Najlepsze jest to, że jeżeli teraz przyjdzie nam na przykład zmienić tekst w batonie, to wystarczy, że zmienimy tekst w przepisie komponentu, a zmiana będzie widoczn
a we wszystkich miejscach, w których wykorzystywaliśmy ten komponent. Jeśli brzmi skomplikowanie, to bez obaw, to jedynie krótki wstęp i zachęta do nauczenia się Reacta. Na koniec warto dodać, że React to biblioteka stworzona przez Facebook, a więc stoi za nią jedna z największych film technologicznych na świecie. Dzięki temu ma potężne wsparcie zarówno ze strony twórców, jak i społeczności, a więc najprawdopodobniej zostanie z nami jeszcze na długie, długie lata. Jak widzicie, jest więc mnóstwo
powodów, dla których warto dać Reactowi szansę. Kurs trwa ponad dwie godziny, więc podzieliliśmy go na minilekcje. W opisie filmu znajdziesz timestampy, ułatwią one powrót do konkretnej lekcji po przerwie. Dodatkowo w wielu lekcjach wspominamy o materiałach bonusowych. Linki do tych materiałów znajdują się właśnie przy timestampie danej lekcji. Musimy wspomnieć o jeszcze jednej rzeczy. Być może wiesz, że jesteśmy autorami płatnego kursu Reacta Zrozumieć React. Jeśli bierzesz już udział w tym ku
rsie, to zupełnie szczerze w tym filmie nie znajdziesz nowych informacji. Zrozumieć React składa się z 11 modułów, blisko 30 godzin materiałów, wideo i ponad 100 zadań. Ten film, który właśnie oglądasz, to zaledwie mała część materiału, który poruszamy w dwóch pierwszych modułach, Fundamenty i Stan. Jak widzisz, sam pierwszy moduł trwa tyle co ten film. Pomimo tego, że korzystamy z niektórych przykładów z kursu, to w samym kursie bardzo dokładnie przechodzimy przez wszystkie zagadnienia i omawia
my wiele dodatkowych. Ale jeśli jeszcze nie bierzesz udziału w kursie, no to oczywiście ten film, który właśnie oglądasz i tak nauczy Cię bardzo dużo nowych rzeczy i da Ci solidne podstawy. A jeśli nasz pełnoprawny kurs brzmi ciekawie, to możesz o nim więcej przeczytać na stronie zrozumiećreact.pl Do pierwszej edycji dołączyło ponad pół tysiąca osób i jego recenzje są naprawdę świetne. Niedługo ruszamy z kolejną edycją i co ważne, dajemy gwarancję satysfakcji. Kurs możesz przetestować i jeśli ni
e przypadnie Ci do gustu, to masz aż dwa tygodnie na dokonanie zwrotu. Nie przedłużajmy już i przejdźmy do nauki Reacta. Żeby rozpocząć pracę z Reactem, tak naprawdę potrzebujemy tylko przeglądarki internetowej i edytora tekstowego. Ja będę korzystał z Google Chrome i Visual Studio Code. Jeśli chodzi o rozszerzenia do Visual Studio Code, to ograniczę się jedynie do dwóch. ESLinta, dzięki któremu edytor będzie mnie informował o błędach, które popełniłem i Prettiera, dzięki któremu po każdym zapis
aniu pliku, napisany przeze mnie kod zostanie automatycznie przeformatowany. Jeśli nie znacie tych rozszerzeń, to możecie zainstalować je wchodząc w zakładkę Extensions i wpisując najpierw ESLint, a później Prettier. Prettier wymaga również drobnego setupu, o którym nagraliśmy osobny filmik. Link do niego znajdziesz w opisie. W tym filmie spróbujemy krok po kroku stworzyć prostą aplikację w React. Będzie to lista kontaktów, którą widzisz teraz na ekranie. Stwórzmy prosty plik index.html. W nim s
korzystajmy ze skrótu wykrzyknik plus tab, żeby dodać na stronie bazowy szkielet.html. Otwórzmy ten plik index.html w naszej przeglądarce. Wiemy już, że React to nic innego jak zbiór javascriptowych funkcji, które ułatwiają nam stworzenie aplikacji. Jak więc dodać React do naszej strony? Istnieje na to kilka sposobów, ale nie wszystkie są dobre. Przykładowo możemy dodać React na stronie za pomocą klasycznego script tagu, tak jak dodajemy zwykłe pliki JS. Skąd wziąć plik z kodem Reacta? Wystarczy
wpisać w Google React CDN i po przejściu w pierwszy wynik widzimy dwa script tagi z linkami. Jeśli otworzymy pierwszy z nich w osobnej karcie to zobaczymy, że faktycznie jest on po prostu zbiorem javascriptowych funkcji. Możemy więc skopiować oba te script tagi i wkleić do naszego body. Dlaczego używamy dwóch różnych script tagów? Wyjaśnimy to już za chwilę. Na razie przejdźmy do naszej strony w przeglądarce. Jak widzimy nie dzieje się na niej nic szczególnego. Jeśli jednak otworzymy DevTools i
w konsoli wpiszemy React to zobaczymy zaimportowany obiekt React wraz z pełnią jego możliwości. Dodawanie Reacta do swojego projektu za pomocą script tagów działa ale nie jest najlepszym pomysłem. Wyobraźmy sobie, że z jakiegoś powodu serwis przechowujący kod Reacta pod tym linkiem przestaje działać. Wraz z nim przestaje wtedy działać nasza strona. W końcu brakuje na niej Reacta. Pozbądźmy się więc całego pliku index.html i postawmy Reactowy projekt tak jak robi się to w codziennej pracy. Zalec
aną alternatywą dla korzystania z CDN jest zainstalowanie npm-owej paczki Reacta w naszym projekcie. Zanim przejdziemy dalej upewnijmy się, że mamy zainstalowanego Node.js. Otwórzmy terminal i wpiszmy komendę node-v. Jeśli w terminalu zobaczymy wersję Node wszystko ok. Jeśli widzisz error node is not recognized as an internal or external command operable program or batch file w opisie filmu znajdziesz link do strony Node. Przejdź na nią, pobierz obecną wersję i zainstaluj ją na swoim komputerze.
Dla pewności zrestartuj Visual Studio Code. Moglibyśmy dodać React do naszego projektu krok po kroku instalując paczkę za pomocą npm-a a następnie ustawiając wszystkie dodatkowe narzędzia potrzebne do odpowiedniego działania Reacta. Ale są już narzędzia, które sprawiają, że ten proces jest szybszy, prostszy i przyjemniejszy. Przez wiele lat dostawiania projektów Reactowych korzystało się z narzędzia zwanego Create React App. Niestety nie wytrzymało ono zbyt dobrze próby czasu. W porównaniu do n
owych alternatyw działa wolno i topornie. Oficjalna dokumentacja Reacta zaleca wykorzystanie frameworka Next.js do postawienia Reactowego projektu. Next jest świetnym narzędziem zwłaszcza do tworzenia dużych, kompleksowych projektów w Reactie. Ale wykorzystanie go do postawienia swoich pierwszych kroków w Reactie jest trochę jak strzelanie z armaty do wróbli. W tym filmie skorzystamy ze świetnego narzędzia o nazwie Vit. Vit to narzędzie służące do stawiania projektów, dewelopowania ich lokalnie
i tworzenia z nich paczek z kodem, które finalnie wrzucamy na nasze strony internetowe. Vit działa na podobnej zasadzie co Create React App, ale jest szybszy, bardziej stabilny i niesamowicie wygodny, o czym zaraz się przekonamy. Żeby użyć Vit, w konsoli wpisujemy npm create vit maupa latest. Vit rozpoczyna proces stawiania projektu i zada nam kilka pytań, na które odpowiemy. Wpisujemy nazwę projektu, np. kurs Reacta. Wybieramy framework, z którego korzystamy. W naszym przypadku jest to oczywiśc
ie React, ale jak widzicie, Vit można też wykorzystać do postawienia projektu w innych narzędziach, takich jak Svelte, Solid czy Quick. Klikamy Enter. Wybieramy wariant. Na potrzeby tego wprowadzenia wybieramy Javascript. Widzimy, że w naszym projekcie pojawiły się nowe pliki, ale to jeszcze nie wszystko. Zgodnie z instrukcją przejdźmy do folderu o nazwie, którą podaliśmy, czyli cd kurs Reacta i wpiszmy npm install. Po skończonej instalacji wpiszmy npm run dev. Jeśli wszystko poszło w porządku,
to możemy przytrzymać Alt i kliknąć w przycisk lub jeśli jesteśmy na Macu, przytrzymać Command i kliknąć w przycisk i wtedy w naszej przeglądarce powinna pojawić się działająca lokalnie aplikacja Reactowa postawiona za pomocą Vit. Nasz Reactowy projekt działa i jest dostępny pod adresem wpisanym w konsoli. Jeśli w niego wejdziemy, to zobaczymy generyczną aplikację stworzoną przez Vit. Możemy zamknąć konsolę, bo na razie nie będzie nam potrzebna. Po prostu pamiętajmy o tym, żeby nie przerywać pro
cesu. Niech on w tle cały czas będzie uruchomiony. Sprawdźmy wygenerowane pliki. Index.html wygląda zawsze znajomo. Jeśli go otworzymy, no to zobaczymy, że tak naprawdę niewiele się tu dzieje. W boti mamy tylko div o id root i skrypt z linkiem do pliku main.jsx. JSX to w dużym skrócie język pomocniczy służący do pisania i tworzenia aplikacji w Reactie. Cóż, JSX nie jest poprawnym rozszerzeniem dla pliku, który możemy załadować za pomocą skrypt tagu. Gdybyśmy po prostu stworzyli od zera projekt z
plikiem index.html, w którym próbujemy dodać plik JSX, to w konsoli zobaczylibyśmy jeden wielki error. Na szczęście w projekcie postawionym przy pomocy Vit możemy bez ograniczeń pracować na plikach JSX, ponieważ Vit odwala za nas brudną robotę i zamienia pliki JSX na JS, które są rozpoznawalne dla przeglądarki. Sprawdźmy więc ten enigmatyczny plik main.jsx znajdujący się w folderze src. Po pierwsze mamy kilka importów. Jeśli potrzebujesz powtórki z importów i eksportów, to sprawdź nasz materiał
dostępny w opisie tej lekcji. Najpierw importujemy react z paczki reacta, a następnie react-dom z paczki react-dom. Działa to na podobnej zasadzie co dodanie do naszej strony skrypt tagów z linkami do obu tych bibliotek. Jeśli pamiętasz, to na początku wkleiliśmy właśnie dwa skrypty i jeden z nich odpowiadał za bibliotekę react, a ten drugi odpowiadał za bibliotekę react-dom i już powoli przechodzimy do wyjaśnienia różnicy między tymi dwoma bibliotekami. Więc tak naprawdę tutaj zaimportowanie t
ych dwóch bibliotek z naszych node modules jest ekwiwalentne do dodania tych dwóch skrypt tagów. Ale właśnie dlaczego potrzebujemy aż dwóch bibliotek? React służy między innymi do tworzenia elementów reactowych. Jak stworzyć taki reactowy element? Możemy do tego wykorzystać specjalną reactową funkcję. W naszym pliku main.jsx stwórzmy stałą element i przypiszmy do niej wywołanie react create element. Create element jako pierwszy argument przyjmuje nazwę tagu, który chcemy stworzyć. Wpiszmy więc t
utaj div. Następnie wywołajmy console.log element. Przejdźmy teraz do naszej strony i zobaczmy co pojawiło się w konsoli. Widzimy, że pojawił się w niej obiekt. Jest to bardzo ważna informacja. Być może najważniejsza w całej nauce Reacta. Elementy tworzone za pomocą Reacta to zwykłe javascriptowe obiekty. Różnią się one od reprezentacji elementów w drzewie domu, którą możemy znać z pracy ze zwykłym JSM. Przykładowo, jeśli w naszej konsoli wpiszemy document.querySelector i poszukamy elementu o id
root to w konsoli pojawi się referencja do elementu znajdującego się w drzewie domu. Tymczasem element reactowy, który wcześniej konsologujemy reprezentowany jest jako obiekt. Jak więc dodać nasz div stworzony za pomocą Reacta do naszej aplikacji? Tutaj z pomocą przychodzi właśnie react-dom. W kodzie wygenerowanym przez Vite wywołujemy react-dom.createRoot i przekazujemy do tego wywołania dokument.getElementById.root czyli referencję do dwo.it.root, który wcześniej widzieliśmy w naszym pliku in
dex.html. react-dom.createRoot tworzy na bazie elementów w drzewie dom specjalny rdzeń, do którego możemy wstrzykiwać elementy reactowe. Jest to tak zwany root element. Żeby wstrzyknąć do niego elementy reactowe wywołujemy metodę render. Zupełnie tak jak dzieje się to w kodzie wygenerowanym przez Vite. Do metody render przekazujemy element reactowy. Nie przejmujmy się na razie tym dziwnym zapisem przypominającym HTML i do render przekażmy nasz stworzony element. Widzimy, że możemy się teraz pozb
yć importu app. Możemy też pozbyć się importu tego pliku w CSS. Z tylami zajmiemy się na sam koniec tego materiału. Po odświeżeniu strony zobaczymy, że zniknęła z niej cała treść. Ale czy na pewno? Jeśli otworzymy DevTools i przeglądniemy elementy, to zobaczymy, że w body, a konkretnie w naszym divie o.it.root znajduje się pusty div. Jest to dokładnie ten div, który stworzyliśmy za pomocą react-create element. Zadaniem reacta jest więc stworzenie elementu reactowego. A zadaniem react-dom jest ws
trzyknięcie go do drzewa dom na naszej stronie. Ale czemu potrzebujemy aż dwóch różnych bibliotek? Być może wiesz, że react można wykorzystać nie tylko do tworzenia aplikacji i stron internetowych, ale również do tworzenia aplikacji mobilnych czy aplikacji VR. To prawda, komponenty stworzone dzięki bibliotece react mogą być użyte na wielu platformach, ale różne platformy inicjalizują reactowe elementy w inny sposób. Przykładowo w aplikacjach internetowych dzieje się to za pomocą biblioteki react
-dom, a w aplikacjach mobilnych za pomocą react-native. I właśnie dlatego do tworzenia pełnoprawnych aplikacji internetowych w react potrzebujemy dwóch bibliotek. React i react-dom. React odpowiada m.in. za tworzenie elementów, a react-dom za wyrenderowanie tych elementów na stronie. Za pomocą react-create-element możemy tworzyć dowolne HTML-owe elementy, nie tylko divy. Przykładowo jeśli przekażemy do niego a zamiast div, to po zapisaniu strona odświeży się automatycznie, a my w naszym divie o
id root zobaczymy pusty tag a. Jak dodać do niego treść albo atrybuty takie jak href? Okazuje się, że react-create-element przyjmuje więcej argumentów. Jako drugi argument możemy przekazać obiekt z atrybutami, które chcemy przypisać do tworzonego elementu. Przykładowo jeśli chcemy, żeby tworzony link prowadził do strony google.pl możemy w obiekcie podać pole href i jako wartość wpisać adres do Google. Po odświeżeniu strony do pustego tagu zostaje dodany atrybut href z podaną przez nas wartością.
Ale nasz tag ciągle jest pusty. Jak dodać treść pomiędzy otwarcie a zamknięcie tagu? Służy do tego trzeci argument przekazywany do react-create-element. Jeśli po przecinku wpiszemy string google i zapiszemy nasz plik to na naszej stronie pojawi się element a linkujący do google.pl z treścią google. Możemy powiększyć sobie trochę całość, żeby lepiej widzieć efekty naszej pracy. Jeśli klikniemy teraz w nasz link to zostajemy przekierowani na stronę Google, więc link działa jak najbardziej poprawn
ie. Możemy na chwilę zamknąć naszą listę plików, bo będziemy teraz głównie pracować w tym pliku main.jsx. Poznaliśmy więc podstawową metodę tworzenia elementów reactowych. Ale taki zapis jest dość niewygodny i nieintuicyjny. W końcu jesteśmy przyzwyczajeni do tworzenia HTML-owych elementów za pomocą strzałkowych nawiasów. I tutaj z pomocą przychodzi nam właśnie JSX. To skrót od javascript, xml i jak podpowiada nam sama nazwa, jest on językiem dzięki któremu możemy używać zapisu HTML w naszym kod
zie javascriptowym. Bez JSX nie jest to możliwe. No sprawdźmy sami. Otwórzmy konsolę i spróbujmy wpisać w niej kod HTML. Jak widzimy nie jest on rozpoznawalny dla silnika javascriptowego. Tymczasem jeśli wrócimy do naszego pliku main.jsx i spróbujemy użyć zapisu HTML np. w konsol.logu to po zapisaniu pliku strona odświeża się automatycznie a my widzimy, że po pierwsze nie mamy żadnych errorów i program działa normalnie. Po drugie w konsoli pojawia się kolejny obiekt, który wygląda bardzo podobni
e do tego pierwszego obiektu. Pierwszy obiekt reprezentuje nasz stworzony element za pomocą react-create-element. Drugi obiekt reprezentuje element stworzony za pomocą tego jsx'owego zapisu wyglądającego jak zwykły html tak h1. Jeśli chodzi o wartości tych obiektów no to jak widzimy różnią się one m.in. polem type bo dla pierwszego tak jak to tutaj sami podaliśmy type jest równe a a dla drugiego type jest równe h1 czyli nazwa tego tagu który zastosowaliśmy. Dzieje się tak ponieważ zapis elementu
w jsx finalnie zostanie stranspilowany do wywołania react-create-element. Co to znaczy? Tak jak podkreśliliśmy zapis jsx'owy czyli ten zapis przypominający nieco kod html nie jest zrozumiały dla przeglądarki. Dlatego nie możemy go po prostu wrzucić na stronę. W naszym projekcie w momencie gdy zapiszemy plik jsx wit przeanalizuje go, znajdzie zapis jsx i za kulisami zamieni go na wywołanie react-create-element. I to właśnie kod z użyciem react-create-element zostanie dostarczony do naszej przegl
ądarki. W uproszczeniu można powiedzieć że strona którą widzimy nie korzysta z plików jsx w projekcie tylko z plików js które wit stworzył za kulisami. Wynikowe pliki js'owe na dowolnej stronie używającej reacta nie będą więc zawierały zapisów jsx ale za to znajdziemy pełno wywołań react-create-element. Samodzielne ustawienie takiego procesu byłoby kłopotliwe i czasochłonne na szczęście dzięki wit jest to szybkie i bezbolesne. Żeby stworzyć reactowe elementy za pomocą react-create-element używam
y trzech argumentów. Nazwy tagu, obiektu z atrybutami oraz treści tagu. Żeby osiągnąć ten sam cel w jsx możemy wykorzystać syntaks podobny do htmlowego. Spróbujmy więc stworzyć nasz element a za pomocą jsx'a. Wpisujemy const element in jsx i teraz nazwę tagu deklarujemy wpisując go w strzałkowych nawiasach. Atrybuty deklarujemy wpisując je w otwarciu tagu zupełnie tak jak robimy to w zwykłym html'u. Treść deklarujemy wpisując ją pomiędzy otwarcie i zamknięcie tagu. Jeśli przekażemy teraz element
in jsx do metody render to po zapisaniu widzimy że zmieniła się jedynie treść ale jeśli zinspektujemy nasz element to widzimy że dalej jest on tagiem a i dalej ma link do googla. Więc tak naprawdę w dużo prostszym zapisie uzyskaliśmy dokładnie ten sam efekt co przed chwilą. I w codziennej pracy z reactem to właśnie w taki sposób tworzy się elementy reactowe. Prawdopodobnie nigdy nie skorzystasz bezpośrednio z react-create element ale chciałem wyjaśnić Ci co dzieje się za kulisami bo takie zrozu
mienie podstaw bardzo pomoże Ci w dalszej nauce reacta i zaowocuje w przyszłości. Niestety w tym stosunkowo krótkim filmie nie mamy zbyt dużo czasu żeby zagłębiać się w każdy niuans i porozmawiać o wszystkich mechanikach reacta. Skupiamy się na podstawach które pozwolą Ci postawić pierwsze kroki. Jeśli podoba Ci się nasz sposób tłumaczenia i wiesz że chcesz kontynuować naukę reacta po skończeniu tego filmu to zapraszamy na stronę zrozumieć-react.pl Możesz na niej poczytać o naszym pełnym kursie
reacta w którym przedstawiamy dokładnie wszystkie kluczowe mechaniki potrzebne do tworzenia aplikacji reactowych i zrozumienia jak działa to narzędzie. A tymczasem wróćmy już do tworzenia elementów za pomocą JSX. JSX to więc nic innego jak specjalny język pomocniczy służący do szybszego tworzenia reactowych elementów poprzez łączenie javascriptu z HTML. No ale tak naprawdę możesz teraz zadać bardzo zasadne pytanie. Czy nie prościej byłoby po prostu stworzyć zwykły HTMLowy element a albo h1? Co t
ak właściwie daje nam łączenie javascriptu z HTMLem? No i właśnie zaraz do tego przejdziemy bo teraz omówimy sobie możliwości JSX. W naszym pliku main.jsx możemy pozbyć się na razie tych konsol logów i elementów i stworzyć nową stałą element, która na razie niech będzie po prostu pustym divem. Przekażmy ją do metody render. Jak widzimy możemy się teraz też pozbyć importu reacta. JSX pozwala nam również na wygodne używanie javascriptu w HTMLu w celu wyświetlenia dynamicznych danych. Spójrzmy na t
en przykład. Powiedzmy, że chcielibyśmy na naszej stronie wyświetlić aktualną godzinę. W naszym pliku main.jsx możemy stworzyć stałą currentDate i przypisać do niej wartość wywołania newDate. Następnie możemy stworzyć stałe hours i minutes i kolejno przypisać do nich godziny i minuty pobrane z naszej stałej currentDate wskazującej aktualną datę. Jeśli skonsologujemy hours i minutes i otworzymy konsolę naszej aplikacji to zobaczymy, że godzina się zgadza, bo dokładnie u mnie jest teraz 18.44. Nas
z div element pojawia się już na stronie, ale jest pusty. Chcielibyśmy w nim wyświetlić daną godzinę. Jeśli mielibyśmy to zrobić w tradycyjny sposób Vanilla.js nie mając do dyspozycji Reacta to musielibyśmy najpierw znaleźć dany element na stronie a potem wstrzyknąć do niego odpowiednią wartość tekstu. JSX pozwala to jednak zrobić dużo prościej. Jeśli za pomocą JSX chcemy do tego naszego zapisu HTML przekazać wartość javascriptową to musimy użyć tak zwanego JSX expression albo mówiąc potocznie c
lammer. Pomyślmy o tym w ten sposób. Jeśli w naszym tagu użyjemy clammer to przestajemy pisać w syntaksie podobnym do HTML i wchodzimy do świata javascriptu. Dzięki clamrom mamy dostęp m.in. do wszystkich zdefiniowanych zmiennych i stałych w scope'ie tej funkcji. Jeśli nie wiesz czym jest scope to koniecznie sprawdź nasz dodatkowy materiał na ten temat. Jeśli w clammer zapiszemy nazwę jakiejś zmiennej czy stałej to clamry wyświetlą jej wartość na ekranie. Ale uwaga spróbujmy wpisać np. w clammer
wartość hours. Po zapisaniu widzimy, że na ekranie nie pojawia się nic. A dzieje się tak dlatego, że JSX obowiązują nas również wszystkie zwykłe zasady javascriptowe. Zwróćmy uwagę, że element jest zdefiniowany przed hours. A oznacza to, że w momencie w którym próbujemy przekazać tutaj hours hours jeszcze nie jest zdefiniowane. Musimy więc zawsze zwracać na to uwagę. Ale jeśli przeniesiemy element tak żeby znajdował się za definicjami naszych stałych i zapiszemy teraz nasz kod to widzimy, że na
stronie pojawia się 18. A więc tak jak powiedzieliśmy dzięki clamrom mamy dostęp do całego scope tego pliku. Przekazujemy więc do nich hours i wartość hours zostanie wyświetlona na ekranie. No ale potrzebujemy też minut. Na szczęście nie musimy się ograniczać tylko do jednej pary clammer. Jeśli w naszym divie obok pierwszej pary clammer dodamy drugą parę clammer a w niej użyjemy stałej minutes to po zapisaniu widzimy, że na ekranie pojawia się dokładna godzina zarówno z godzinami jak i z minuta
mi. Ale co ważne pomiędzy clamrami możemy dalej używać zwykłego kodu html. Więc jeśli dodamy pomiędzy nimi dwukropek zamiast spacji to oczywiście wyświetli się on na ekranie jako zwykła część kodu html. Clammery możemy również wykorzystywać do wyświetlenia wartości javascriptowych typu number. Jeśli stworzymy stałą number content i przypiszemy jej wartość 13 to jeśli pozbędziemy się naszych aktualnych wartości i w tej clamrze wpiszemy number content no to oczywiście 13 pojawi się na ekranie. Jeś
li chodzi o numbery to nie musi być od razu zadeklarowany number. Możemy na przykład przypisać tutaj operację arytmetyczną. Czyli jeśli wpiszemy 13 plus 7 no to do clammer zostaje przekazana 20 i też 20 wyświetla się na ekranie. Co więcej nie musimy przekazywać wartości do clammer za pomocą zmiennych czy stałych. Tak naprawdę możemy wyciąć tę wartość pozbyć się deklaracji tej stałej i wkleić ją bezpośrednio do clammer. Widzimy, że efekt jest taki sam możemy tutaj dla pewności zmienić wartość i w
idzimy, że pojawia się 21. Oczywiście do clammer możemy też wpisać wartość typu string i ona też pojawi się na ekranie i nic nie stoi na przeszkodzie do przekazania stringa bezpośrednio do clammer. Także tutaj trzeba być ostrożnym jeśli chodzi o używanie stringów bezpośrednio w clamrach no bo w tym przypadku widzimy, że pomimo tego, że korzystamy z takiej nazwy jak nazwa tej stałej text no to przekazujemy ją jako string, prawda? W cudzysłowiu. Dlatego to właśnie napis text zostanie wyświetlony b
ezpośrednio w clamrach. I moglibyśmy teraz lecieć przez 100 kolejnych przykładów ale zamiast tego lepiej będzie jeśli wykształcimy sobie model myślenia o tym co można przekazać do tych magicznych clammer. Pierwsza zasada. Musimy przekazać do nich tak zwane javascript expression. Javascript expression to po prostu kawałek kodu, który zwraca wartość. Możemy to lepiej zrozumieć eksperymentując trochę w konsoli. Jeśli po prostu zdefiniujemy stałą na przykład x równe 10 to nic się nie stanie. Wartość
nie zostanie zwrócona. Ale jeśli odwołamy się teraz do tej zmiennej i po prostu wpiszemy x i naciśniemy enter to w konsoli wyświetli się zwrócona wartość. Tak więc jeśli w JSX spróbujemy w clamrach dodać na przykład deklarację stałej to widzimy, że otrzymujemy ostrzeżenie już na poziomie edytora. No i jeśli spróbujemy zapisać nasz kod i strona się odświeży to widzimy, że przestaje ona działać. To samo tyczy się na przykład pętli. Do clamr możemy więc przekazywać jedynie zwracane wartości a w pr
zypadku zmiennych i stałych ich deklaracje musimy wyciągnąć po zatworzony element. Także jeśli wpiszemy sobie tutaj teraz const x no to tak jak widzieliśmy już wcześniej po przekazaniu go do clamr wszystko wraca do normy. Ta restrykcja nie ogranicza się jedynie do deklarowania zmiennych i stałych. Podobnie jest z funkcjami. Wyobraźmy sobie, że chciałbym zadeklarować prostą funkcję która zwróci mi losowy numer od 1 do 100 i chciałbym ten numer wyświetlić w naszym reaktowym elemencie. Jeśli spróbu
ję to zrobić w clamrach to niestety natrafiamy na podobny problem co przed chwilą. W konsoli widzimy error warning functions are not valid as a react child czyli w luźnym tłumaczeniu uwaga funkcje nie mogą być przekazywane jako react child. React child to wartość zagnieżdżona w innym elemencie w tym przypadku w naszym divie. Wyciągnijmy tę funkcję z clamr i dodajmy ją nad stałą element. Jeśli stworzymy teraz wartość random number i przekażemy ją do clamr to widzimy, że pojawia się na naszej stro
nie losowy numer i z każdym odświeżeniem faktycznie generuje się nowy numer. Po prostu wywołujemy naszą funkcję przypisujemy losowy numer do stałej random number i random number przekazujemy do clamr. Co więcej tak naprawdę w ogóle nie potrzebujemy tej dodatkowej stałej bo get random number możemy wywołać bezpośrednio w naszych clamrach. Po zapisaniu widzimy, że efekt jest dokładnie ten sam. Get random number wywołane zwraca losowy numer który jest przekazywany do clamr. I tutaj bardzo ważna rze
cz w przypadku wywoływania funkcji w taki sposób musimy oczywiście pamiętać że jeśli chcemy użyć wywołania funkcji w clamrach to ta funkcja koniecznie musi coś zwracać i zawierać return. Jeśli nasza funkcja nie zwróciłaby wartości i zamiast tego po prostu konsologowała randomowy numer to po zapisaniu widzimy, że losowe liczby pojawiają się w konsoli ale na stronie nie pojawia się nic. Dzieje się tak dlatego, że funkcje w których brakuje returna zwracają undefined i to właśnie undefined zostaje p
rzekazane do clamr. Jeśli przekażemy do clamr undefined, nul albo dowolny boolean czyli true lub false to na ekranie nie wyświetli się nic. Będziemy korzystać z tego zachowania w przyszłości więc warto je zapamiętać. I jeśli chodzi o funkcje to jeszcze jedna ważna rzecz oczywiście musimy pamiętać o tym żeby tę funkcję wywołać. Nawet jeśli wrócimy do naszego zapisu z returnem ale pozbędziemy się nawiasów czyli po prostu przekażemy do samych clamr definicję naszej funkcji get random number no to w
idzimy, że ponownie nie wyświetla się nic bo po prostu przekazujemy tutaj definicję funkcji i tak naprawdę wróciliśmy do tego problemu który mieliśmy przed chwilą. Po prostu próbujemy tutaj do clamr przekazać definicję funkcji no a my potrzebujemy ją wywołać. A co z obiektami? Zacznijmy powoli tworzyć naszą książkę adresową i stwórzmy obiekt person. Niech posiada on na początek dwa pola name reprezentujące imię i tel reprezentujące numer telefonu. Jeśli spróbujemy przekazać ten obiekt do jsxowyc
h clamr czyli wpiszemy w clamrach person to po zapisaniu no widzimy, że zostajemy zasypani errorami. Objects are not valid as a react child czyli mamy w zasadzie ten sam problem co z funkcjami. Nie możemy obiektów przekazywać jako treści danych elementów reactowych. Używanie obiektów jako treści tagu odpada. Jeśli chcemy pokazać informacje zawarte w tym obiekcie musimy do treści tagu przekazać jego pola osobną. A więc najpierw wpisujemy person name a potem po przecinku możemy wpisać w zwykłym HT
MLowym kodzie tel i tutaj ponownie w clamrach przekazać tę javascriptową wartość person tel. Dzięki temu po zapisaniu strona się odświeża a my widzimy informacje o naszej pierwszej osobie dodane w obiekcie person. Ale uwaga, clamry możemy wykorzystać nie tylko do przekazywania dynamicznej wartości treści do tagów ale również do przekazywania dynamicznych wartości atrybutów. Wyobraźmy sobie, że chcemy nasz numer telefonu objąć w tag a. Nic nie stoi na przeszkodzie żeby w jsx zagnieżdżać w sobie t
agi. Zupełnie tak jak robimy to w zwykłym HTMLu. A więc obejmujemy nasze clamry z person tel w tag a. Żeby link zadziałał poprawnie musimy do atrybutu href podać person tel. Więc zupełnie tak jak w zwykłym HTML wpisujemy href równa się i tutaj bardzo ważna sprawa. Standardowo wartości atrybutów HTML przekazujemy w cudzysłowach. Gdybyśmy po prostu wpisali tutaj w cudzysłowiu wartość person tel to nasz link nie działałby dobrze. Zobaczmy po zapisaniu jeśli zinspektujemy sobie ten element to widzim
y, że wartość href jest równa stringowi person kropka tel. No tak w końcu żeby w jsx używać wartości javascriptowych to powinniśmy objąć je w clamry. A więc spróbujmy dodać pomiędzy cudzysłowami jeszcze dodatkowo clamry i objąć nimi ten person tel. Po zapisaniu no widzimy, że dalej mamy problem bo href jest teraz równy clamra person tel kropka tel i znowu clamra, więc to nie jest poprawna wartość telefonu. Chcielibyśmy tutaj widzieć ten zapis raz, dwa, trzy, cztery, pięć, sześć, zero, zero, zero
. Psst, tak przy okazji tak na serio to nie jest mój prawdziwy numer telefonu. No ale wracając do naszego problemu z href. Jeśli chcemy przekazać atrybut do elementu reaktowego za pomocą jsx expression to musimy pamiętać o tym, żeby usunąć ten cudzysłów. Po tym zabiegu utworzony zostanie tak już z poprawną wartością. Dzięki clamrom href przyjmie wartość person tel. Co więcej jest jeszcze jeden rodzaj wartości, które możemy przekazywać do clamr. Okazuje się, że clamr możemy używać do renderowania
innych reaktowych elementów. Przykładowo jeśli wytnę cały ten tak a z naszego diva a następnie stworzę stałą tel element i przypiszę do niej wyciętą wartość tak u a to widzimy, że oczywiście tak a znika teraz z naszego diva. Ale mogę teraz tę stałą tel element przekazać w clamrach do naszego diva. Pamiętajmy, że tak naprawdę pod maską jest to wartość javascriptowa. Jest to ciągle wywołanie react create element, więc mogę to wywołanie tutaj pośrednio przekazać do clamr i teraz po zapisaniu o str
ona się odświeża i my widzimy nasz tel element ponownie w naszym divie. Link zostanie wyrenderowany na stronie zupełnie tak jak przed chwilą. Co więcej mogę teraz użyć tej stałej wielokrotnie po to żeby wyświetlić ten link kilka razy. I po bardzo długim wstępie zaczynamy w końcu dostrzegać możliwości reacta. Stworzenie reużywalnego elementu i wygodne ustawienie go w JSX jest naprawdę dużo szybsze niż robienie tego ręcznie w zwykłym HTML. Przykładowo jeśli musielibyśmy teraz zmienić numer telefon
u to wystarczy, że zrobimy to w jednym miejscu. Po zapisaniu zmiana będzie widoczna we wszystkich miejscach w których użyliśmy naszego elementu. Powiedzmy, że chcielibyśmy wyświetlić tytuł naszej aplikacji w tagu h1 pod nim imię w tagu h2 a pod imieniem numer telefonu w tagu h3. Jeśli spróbujemy umieścić te tagi obok siebie to już na poziomie edytora widzimy bardzo ważny error. JSX expression must have one parent element. A więc wyrażenia JSX muszą mieć tylko jeden parent element. Parent element
to w tym kontekście element, który obejmuje inne elementy. Chcąc zwrócić obok siebie dwa lub więcej elementów to trochę tak jakbyśmy chcieli przypisać do jednej zmiennej dwa obiekty naraz albo z funkcji zwrócić dwie wartości. Jeśli chodzi o przekazywanie reactowych elementów czy to do metody render czy przypisywanie ich do stałych to zawsze musimy przekazać tylko jeden parent element. Oznacza to, że nasz problem możemy naprawić obejmując wszystkie te tagi heading pojedynczego diva. Dzięki temu
spełniamy tę zasadę jednego parent komponentu. Widzimy, że error znika a nasza lista kontaktów wyświetla się już poprawnie. Jeśli chodzi o elementy znajdujące się w środku tego elementu to tutaj nie mamy już żadnych ograniczeń i możemy dodać ich tyle ile chcemy. Ale to rozwiązanie ma minus, bo musimy dodać kolejny element HTML w tym przypadku nasz div, którego jedynym zadaniem jest objęcie innych elementów. I oczywiście nie ma to znaczącego wpływu na wydajność aplikacji ale może na przykład wpły
nąć na jej layout w zależności od tego jakie mamy style. Na szczęście react daje nam alternatywę w postaci tak zwanych fragmentów. Fragment wygląda tak jakbyśmy chcieli użyć tagu HTML ale nie wpisali jego nazwy. Jego zadaniem jest objęcie zgrupowanych elementów. Przewagą fragmentu nad divem jest to, że nie generuje on dodatkowego elementu w domie. Jeśli odpalimy teraz devtools to widzimy, że rzeczywiście wyświetlamy h1, h2 i h3, ale nie mamy tutaj dodatkowego elementu, który je obejmuje. Fragmen
t nie dodał więc kolejnego elementu do domu i jednocześnie pozwolił nam spełnić zasadę pojedynczego parent element. Możemy teraz rozszerzyć nasz obiekt z danymi i przykładowo dodać do niego miejsce zamieszkania. A następnie przekazać to do naszego obiektu. A następnie przekazać nowe pole do fragmentu. Widzimy więc, że podobnie jak w przypadku obejmowania elementów w zwykły div, możemy dodać ich w środku tyle ile chcemy. Wyświetlamy już informację o pierwszej osobie. Spróbujmy teraz dodać informa
cję o kolejnej osobie. Skopiujmy constPerson i stwórzmy stałą newPerson. Niech naszą drugą osobą będzie kacper. No i zmieńmy lekko jego numer telefonu. No i żeby wyświetlić teraz informację o nowej osobie, to w naszym elemencie ponownie możemy zacząć dodawać kolejne tagi h2 i h3, a więc wpisujemy h2 i w klamrach newPerson i imię. Widzimy więc, że imię kacper wyświetla się już poprawnie. Przejdźmy teraz do wyświetlenia numeru telefonu kacpera, więc wpisujemy h3, tel. No i właśnie, mamy lekki prob
lem. Jeśli użyjemy naszej stałej tel element, to wyświetli się numer pierwszej osoby. W końcu tel element zdefiniowaliśmy używając danych z obiektu person. Oczywiście możemy teraz stworzyć nową stałą newTel element, ale jak pewnie się domyślasz, to rozwiązanie słabo się skaluje. Co jeśli dodamy nową osobę? Będziemy tworzyć kolejną stałą i nowy zestaw elementów? No nie jest to zbyt wygodne. Na szczęście możemy skorzystać z podstawowego mechanizmu, aby rozwiązać nasz problem. Wystarczy zdefiniować
funkcję, do której przekażemy odpowiednie argumenty. W naszym pliku main.jsx stwórzmy więc funkcję. Nazwijmy ją tel. I oczywiście nie ma tutaj znaczenia, czy to będzie funkcja strzałkowa, czy funkcja zapisana w klasyczny sposób za pomocą słowa kluczowego function. I z naszego tel zwróćmy element a, który będzie wyświetlał dane nowej osoby. Dzięki temu funkcja tel po wywołaniu zwraca element, który w niej zdefiniowaliśmy. Ale jak właściwe ją wywołać? Na razie mamy tylko jej definicję, a to oczyw
iście nie wystarczy do wyświetlenia elementu na stronę. To trochę tak, jakbyśmy po prostu patrzyli na przepis kuchenny i czekali aż ciasto samo się zrobi. Możemy spróbować wywołać tę funkcję w jsx expression. Tak jak robiliśmy to chwilę wcześniej w przypadku naszej testowej funkcji getRandomNumber, a więc wpisujemy sobie tutaj w klamrach tel i wywołujemy tę funkcję. Po zapisaniu strona się odświeża i widzimy, że to faktycznie działa. W końcu wywołujemy funkcję, która zwraca reactowy element. No
ale jeśli spróbujemy teraz wywołać tel w drugim stagów a3 to ponownie wracamy do tego samego problemu. W obu miejscach wyświetla się nam ten sam element. Na szczęście naszą funkcję możemy sparametryzować. W jej definicji dodajmy parametr tel. Możemy teraz przekazać ten parametr do klamer zarówno jako href, jak i jako treść tagu a. Dzięki temu kiedy wywołujemy funkcję tel w klamrach, możemy do niej przekazać odpowiednie numery telefonu. Dla pierwszej osoby przekazujemy więc person tel, a dla drug
iej newPersonTel. No i widzimy, że mamy efekt, który chcieliśmy. Wyświetlają się dwa różne numery odpowiednie dla danej osoby. Skorzystaliśmy więc ze zwykłej funkcji po to, żeby zapewnić sobie większą elastyczność. Tylko, że funkcja tel to nie do końca jest zwykła funkcja. Jest to reactowy komponent. Do tej pory tworzyliśmy reactowe elementy. Czy to za pomocą react-create element, czy to za pomocą syntaksu JSX. Tak jak robimy to jeszcze tutaj w przypadku naszej stałej tel element. Komponenty i e
lementy to jednak nie to samo. Koncepcyjnie komponenty to przepisy, dzięki którym możemy tworzyć wspomniane już elementy. Gdybyśmy mieli porównać to do życiowego przykładu. Przepisy w książce kucharskiej to komponenty. Ciastka, którą pieczemy bazując na tych przepisach to elementy. Jak stworzyć komponent w React? Technicznie komponenty to po prostu funkcje. Ale zwróćmy uwagę, że zapisaliśmy tę funkcję z wielkiej litery. Nie jest to przypadek, mało tego jest to wymóg. React sprawdza nazwy tagów i
to właśnie po wielkiej literze na początku poznaje, że ma do czynienia z tagiem stworzonym przez nas. A nie z natywnym tagiem HTML, takim jak H1, A czy nawet Body. Ma to wpływ na działanie całej aplikacji, więc koniecznie zapamiętajmy tę zasadę. Funkcje definiujące komponenty nazywamy z wielkiej litery. Ale jeśli chodzi o nazewnictwo to w zasadzie jedyny wymóg. Najważniejszą zasadą w tworzeniu komponentów jest to, że ich funkcje muszą zwracać wartość. W przypadku naszego komponentu tą zwróconą
wartością jest element a. Takie wywołanie funkcji komponentu to tworzenie tak zwanych instancji komponentu. Bierzemy nasz przepis, czyli komponent, tworzymy jego instancję, która ostatecznie zwróci reactowe elementy. Terminy komponent i element są przez wiele osób używane zamiennie, ale zrozumienie ich definicji pomoże nam lepiej poukładać zdobytą wiedzę i ułatwi dalszą naukę. No i teraz bardzo ważna rzecz. Wywołanie tej funkcji bezpośrednio w klamrach nie jest poprawnym sposobem korzystania z k
omponentów. Ten sposób teoretycznie działa, ale prowadzi do bugów i problemów z wydajnością. JSX pozwala nam na wywołanie funkcji komponentów w bardziej intuicyjny sposób. Jedyne co musimy zrobić to w naszym JSXowym syntaksie dodać tag, którego nazwa jest tą samą co nazwa komponentu. W naszym przypadku tel. Zwróćmy uwagę, że tagu nie podajemy już w klamrach, a wpisujemy go tak jak standardowe tagi HTML. Jest to kolejne ułatwienie, które pozwala nam tworzyć reactowe aplikacje w sposób zbliżony do
znanych nam klasycznych metod. W końcu do tworzenia zwykłych stron używamy zapisów takich jak h1, nav czy img. Oczywiście tel nie jest ogólnie dostępnym tagiem HTML, ale react w połączeniu z JSX pozwala nam w pewien sposób tworzyć nasze własne tagi. No ale zaraz, po zapisaniu widzimy, że aplikacja przestaje działać. Co się dzieje? Zwróćmy uwagę, że przed chwilą, kiedy wywoływaliśmy jeszcze funkcję tel w klamrach po to, żeby stworzyć elementy, przekazywaliśmy do tej funkcji numer telefonu, który
ostatecznie był wyświetlany w zwracanym elemencie a. Wpisując po prostu tel w tagach JSXowych, to mniej więcej tak jakbyśmy wywołali tę funkcję tel, ale nie przekazali do niej żadnych argumentów. Jak więc przekazać argumenty do tej funkcji wywołanej za pomocą tagów JSXowych? Możemy zrobić to dokładnie tak samo, jak do zwykłych HTMLowych tagów przekazujemy atrybuty takie jak href, class czy src. Takie wartości przekazywane do komponentów nazywamy w reactie propertiesami albo mówiąc bardzo zwycza
jowo propsami. Przekazywanie propsa składa się z dwóch części. Wybrania jego nazwiska, Przekazywanie propsa składa się z dwóch części. Wybrania jego nazwy i przypisania do niego wartości. W przypadku przekazywania propsów do komponentów reactowych, sami musimy wymyślić nazwę. Skoro chcemy, żeby nasz props reprezentował numer telefonu pojawiający się w tagu a, to nazwijmy go po prostu tel. Następnie, żeby przekazać wartość wpisujemy znak równości i w klamrach będziemy podawać wartość, którą chcem
y w tym propsie przekazać. W naszym przypadku, jako, że mamy tutaj do czynienia z drugą osobą, no to przekazujemy tutaj oczywiście new person tel. Co dalej? Mówiąc w dużym uproszczeniu, taki zapis jest zamieniany na wywołanie funkcji tel z obiektem, w którym pary kluczy i wartości tworzą wpisane argumenty. Za to wywołanie odpowiada react i obiekty z propsami to jedyny argument, który jest przekazywany do funkcji definiującej nasz komponent. Cóż, widzimy, że nasz komponent dalej nie działa popraw
nie. Dzieje się tak dlatego, że funkcja przyjmuje pojedynczy argument reprezentujący telefon, a my wywołujemy ją z obiektem reprezentującym propsy. Możemy to sprawdzić dodając console.loga w naszej funkcji tel. Wytnijmy zwracany element i dodajmy tutaj body funkcji. Zwróćmy nasz element za returnem, a przed nim dodajmy console.log tel, po to, żeby zobaczyć jakie wartości są przekazywane do funkcji. Po odświeżeniu w konsoli na początku, czy jeszcze przed errorami pojawiają się dwa wyniki. Pierwsz
y pokazuje poprawny numer. Jest to wywołanie tel dla pierwszej osoby. Z kolei drugie wywołanie już przy pomocy zapisu JSX skutkuje pojawieniem się w konsoli obiektu z propsami. Musimy więc dostosować naszą funkcję tak, żeby przyjmowała obiekt. Wystarczy, że zmienimy nazwę parametru na props, no i teraz obiekt, który przychodzi i jest przypisywany do tej zmiennej props, to obiekt z poszczególnymi propsami przekazanymi do tagu tel. A więc jeśli odwołamy się do props tel, to odwołamy się tak napraw
dę do wartości przekazywanej tutaj w tym propertiesie tel. A więc przekazujemy props tel w klamrach zarówno dla href, jak i w treści tagu a. I dzięki temu po zapisaniu i odświeżeniu strony, widzimy, że dla drugiej osoby numer wyświetla się poprawnie, ale mamy teraz z kolei problem z pierwszym elementem. A to dlatego, że tutaj dalej korzystamy z tego zapisu wywołania funkcji bezpośrednio w klamrach. Zamieńmy więc ten zapis na wykorzystanie tagu tel i tutaj podobnie jak w drugim przypadku wpisujem
y propsa o nazwie tel i przypisujemy do niego w klamrach wartość person tel. Pamiętamy o zamknięciu taga, zapisujemy stronę i widzimy, że pojawiają się poprawne wartości zarówno dla pierwszej, jak i drugiej osoby. A jak już jesteśmy przy otwarciu i zamknięciu tagów, to zwróćmy uwagę, że wywołując komponent, tworząc jego instancję, to tak naprawdę nie podajemy do niego żadnej treści. Oznacza to, że możemy skrócić nieco zapis i użyć tak zwanego self-closing tagu. Prawdopodobnie znasz go już z używ
ania tagu img. To jest dokładnie ta sama zasada. Jeśli tak nie ma żadnej treści, to możemy po prostu skrócić ten zapis, jednocześnie go otworzyć i zamknąć. Wtedy wszystkie propsy podajemy pomiędzy tymi strzałkowymi nawiasami po nazwie komponentu, który chcemy użyć. A więc dla krótkiej powtórki. Wywołujemy funkcję tel przekazując do niej obiekt z propsami. Funkcja odczytuje poszczególne pola z propsów i przekazuje je do klamer w tagu a. Zwracany element pojawia się na stronie. Jeśli chodzi o wart
ości przekazywane do propsów, to tutaj nie ma ograniczeń. Możemy wykorzystywać JSX expression i przekazywać do komponentów stringi, numbery, booliny, obiekty, tablice, funkcje, a nawet inne elementy reactowe. Być może u ciebie, tak jak w moim przypadku, w edytorze pojawił się czerwony kolor w miejscu użycia props tel. Po najechaniu na ten JSX expression widzimy error tel is missing in props validation. Error ten pokazuje się, jeśli masz w swoim IDE zainstalowany ESLint i wynika z braku tzw. prop
types. W dużym skrócie, korzystanie z nich polegało na dodawaniu w komponentach specjalnych obiektów wraz z typami opisującymi poszczególne propsy. Dzięki temu, jeśli opisaliśmy dany props jako boolin, a przekazaliśmy do komponentu stringa, to w konsoli otrzymywaliśmy error. Pomimo tego, że prop types był dość popularnym narzędziem przez wiele lat, to odchodzi już do lamusa. Obecnie dużo lepszym wyborem jest po prostu używanie Reacta z TypeScriptem. Nasz kurs jest prowadzony w JavaScript, więc
jeśli nie znasz TypeScripta, to bez obaw, będziesz w stanie ukończyć kurs. Pomimo tego, zachęcamy do spróbowania swoich sił z TypeScriptem. Możesz sprawdzić nasz 3-godzinny, darmowy materiał na YouTubie. Żeby ten warning nas nie denerwował, wystarczy, że otworzymy nasze pliki, poszukamy pliku eslintrc, otworzymy go i tutaj w obiekcie rules dodamy regułę react ukośnik prop types dwukropek zero. Po zapisaniu, zamknięciu eslintrc, widzimy, że problem znika. Przejdźmy dalej i wyświetlmy informacje o
mieście, w którym mieszka druga osoba. A więc wpisujemy h3, miasto i w klamrach newperson.city. I jak widzimy, dwukrotnie tworzymy zestaw tagów h2 i h3 i przekazujemy do nich informacje na podstawie obiektów o tych samych polach. Spróbujmy więc stworzyć komponent, który będzie zwracał tag h2 z imieniem danej osoby, tag h3 z jej numerem telefonu i tag h3 z miastem, w którym mieszka. Zachęcam do spauzowania wideo i podjęcia samodzielnej próby stworzenia takiego komponentu. I jak? Udało się? Jeśli
nie, to bez obaw, zaimplementujemy go teraz krok po kroku. Możemy pozbyć się już naszego tel-element, bo nie będzie nam potrzebne, a nowy komponent nazwać np. person-info. I teraz z person-info zwróćmy po kolei tagi h2, h3 i drugi h3 dla miasta. No i uwaga, tutaj już widzimy, że jest czerwono. Pamiętajmy o tym, że musimy zwracać z komponentów również tylko jeden element. Nie możemy zwrócić kilku elementów obok siebie, a więc całość ponownie obejmujemy w reactowy fragment, a więc tak bez nazwy,
można to tak w uproszczeniu nazwać. Wklejamy wycięte nagłówki. No i jeśli pod naszym tagiem h1 stworzymy teraz instancję komponentu person-info, to tak naprawdę różnicy nie ma żadnej, ale jeśli zinspektujemy sobie naszą stronę, to zobaczymy, że w body, w divie o id root pod listą kontaktów rzeczywiście pojawiają się te nasze puste elementy h2, h3, h3, które dodaliśmy tutaj w naszym komponencie person-info. Musimy do person-info przekazać informacje o imieniu, numerze telefonu i mieście. Zacznijm
y więc od imienia. W otwarciu tagu person-info musimy wymyślić nazwę dla propsa, który będzie przekazywał te informacje o imieniu, więc naturalnie nasuwa się tutaj nazwa name. Następnie przekazujemy jego wartość. Name równa się i w klamrach przekazujemy wartość, którą chcemy podać. Najpierw stwórzmy instancję komponentu person-info dla pierwszej z osób, a więc wpisujemy tutaj person name. No i jak teraz tę informację odczytać w naszym komponencie person-info? Podobnie jak w tel, dodajemy sobie t
utaj parametr props, który reprezentuje obiekt z propsami przekazywanymi do person-info. A więc jeśli w h2 chcemy wyświetlić imię danej osoby, no to w klamrach wpisujemy tutaj po prostu props i odwołujemy się do pola o nazwie danego propertisa, w naszym przypadku name. Po zapisaniu widzimy, że w naszym dodatkowym tagu h2, zaraz pod listą kontaktów, rzeczywiście pojawia się nasze imię. Do komponentu tel przekazywaliśmy tylko jeden propertis, ale tak naprawdę nie ma żadnego ograniczenia, jeśli cho
dzi o liczbę propertisów utworzonych w danym komponencie. Oznacza to, że do person-info możemy przekazać kolejną informację, na przykład teraz o telefonie. Tworzymy więc kolejnego propsa, wpisujemy jego nazwę tel, dwukropek i w klamrach przekazujemy nazwę person tel. Możemy zamknąć nasze pliki, żeby mieć troszkę więcej miejsca na kod. Jak teraz w komponencie person-info odczytać przekazywaną wartość? No pobieramy już informacje o obiekcie reprezentującym propsy. Wystarczy więc, że w tagu h3 wpis
zemy informację tel, dwukropek no i tutaj widzimy, że w naszym starym widoku wykorzystywaliśmy instancję komponentu tel. Czy możemy ją wykorzystać również w innym komponencie? Oczywiście, że tak. Wpisujemy więc tel i przekazujemy jako wartość propertiesu tel props tel. A więc tworzymy najpierw obiekt props przekazując do niego name i tel, a następnie wyciągamy z tego obiektu props telefon i przekazujemy go do komponentu tel, który końcowo ponownie jest odczytywany z propsów i wyświetlany zarówno
jako href, jak i jako treść elementu a. Tak więc widzimy, że instancję komponentów możemy w sobie zagnieżdżać dokładnie tak jak robimy to ze zwykłymi tagami html. Po zapisaniu kodu widzimy, że telefon wyświetla się tutaj poprawnie. Pozostaje nam do naszej instancji komponentu personinfo dodać informacje o mieście, a więc tworzymy props o nazwie city i przekazujemy tutaj person city, a następnie w definicji naszego komponentu w ostatnim pustym h3 wpisujemy miasto no i w klamrach przekazujemy odc
zytaną z propsów wartość city. Po zapisaniu widzimy, że elementy utworzone za pomocą naszego komponentu, jak i elementy, które stworzyliśmy tutaj bezpośrednio w JSX wyglądają dokładnie tak samo. Możemy się więc pozbyć naszego starego zapisu. No i uwaga, spróbujmy teraz wykorzystać personinfo do wyświetlenia informacji o drugiej osobie i zobaczmy jakie to jest proste. Wystarczy tak naprawdę, że skopiujemy instancje naszego pierwszego personinfo i tutaj po prostu zamienimy te wywołania person na n
ew person. Po zapisaniu, jeśli pozbędziemy się tego starego zapisu o informacjach dla new person, widzimy, że strona wygląda dokładnie tak samo, ale zobaczmy jak przyjemniejsze to jest dla oka, prawda? Poszło szybko, prawda? To właśnie wielki plus pracy z komponentami. Co prawda musimy się trochę namęczyć przy ich definiowaniu, ale używanie ich to czysta przyjemność. Jako, że komponent to po prostu funkcja, to dla zachowania porządku w kodzie możemy ją oczywiście przenieść do innego pliku. Wytni
jmy definicję personinfo i w naszym folderze src dodajmy folder components. W folderze components dodajmy plik, który będzie przechowywał nasz komponent personinfo. Jeśli chodzi o nazwę tego pliku, to po pierwsze, powszechną konwencją jest nazywanie pliku z komponentem tak samo jak komponentu, więc w przypadku komponentu personinfo, plik ten nazywamy personinfo. Nie jest to jakaś ścisła reguła i jeśli z jakiegoś powodu chcielibyśmy nazywać plik inaczej, to możemy to zrobić, ale warto trzymać się
popularnej konwencji. Praca z plikami i komponentami staje się wtedy dużo łatwiejsza. Jeśli chodzi o rozszerzenie pliku, to dodajemy rozszerzenie JSX. Dlaczego rozszerzenie JSX, a nie JS? Po pierwsze, niektóre narzędzia, w tym vid, którego używamy, w ogóle nie pozwalają na importowanie plików JS z kodem JSX. Gdybyśmy próbowali to zrobić, to w aplikacji pokazałby się nam error. Dodatkowo, nadawanie plikom rozszerzenia JSX jednoznacznie wskazuje na to, że mamy do czynienia z reactowym komponentem
. Kategoryzowanie pliku na bazie rozszerzeń bardzo pomaga w utrzymaniu rosnących aplikacji, bo w nich będziemy mieli do czynienia nie tylko z plikami JSX, ale również ze zwykłymi plikami JS. Dzięki poprawnym rozszerzeniom będzie nam łatwiej rozróżnić, co jest reactowym komponentem, a co zwykłą JS-ową logiką. Folder src to folder, w którym będziemy trzymali nasze źródła. Na etapie lokalnego developmentu przy uruchomionym devserwerze są one dynamicznie zamieniane na kod JS i serwowane do naszej pr
zeglądarki. Kiedy będziemy chcieli zdeployować naszą aplikację na zewnętrzny hosting, będziemy musieli stworzyć pliki wyjściowe za pomocą komendy npm run build, ale nie będziemy się tym teraz zajmować. Na ten moment zapamiętajmy po prostu, że całą logikę naszej aplikacji i wszystkie komponenty powinniśmy umieszczać w folderze src. Twórzmy i otwórzmy nasz plik. Wklejmy wyciętą funkcję personinfo i dodajmy przed jej definicją export. Tak, żebyśmy mogli używać jej w innych plikach w naszym projekci
e. Widzimy, że mamy problem, bo w pliku personinfo nie mamy dostępu do definicji komponentu tell. Wróćmy więc do pliku main.jsx i wytnijmy również komponent tell. Teoretycznie możemy dodać tę definicję w pliku personinfo. W jednym pliku możemy stworzyć kod JS, a w drugim pliku personinfo. W jednym pliku możemy stworzyć kilka komponentów. Bardzo ważne jest jednak, żebyśmy nie zagnieżdżali w sobie definicji komponentów. To znaczy, jeśli chcemy tutaj zdefiniować tell to powinniśmy zrobić to poza fu
nkcją personinfo. Umieszczenie definicji komponentów bezpośrednio w funkcji definiującej inny komponent prowadzi naprawdę do brzydkich błagów. Ale istnieje jeszcze lepsze wyjście. Możemy tell zdefiniować w osobnym pliku. Tworzymy więc w naszym folderze components plik o nazwie tell.jsx i wklejamy w nim definicję tell. Eksportujemy ją. Zamykamy plik i w naszym personinfo importujemy po prostu komponent tell. Możemy to oczywiście zrobić wpisując import ręcznie. Dzięki temu pozbywamy się errora. Po
zostaje nam zaimportować samo personinfo w pliku main.jsx No bo widzimy, że mamy tutaj teraz problem. Personinfo jest naddefine, więc ponownie możemy wpisać import ręcznie, ale możemy też skorzystać ze skrótu klawiszowego ctrl i albo command i na maku. Wtedy wyświetli się lista potencjalnych importów. Wybieramy sobie ten personinfo. I voila. Aplikacja wygląda dokładnie tak samo. To dobrze, bo to znaczy, że wyeksportowane komponenty działają poprawnie. Dla pewności możemy zmienić tutaj tekst w ty
m osobnym pliku i widzimy, że zmiany zostają zaaplikowane. Podobnie dla komponentu tell. Gdybyśmy teraz chcieli dokonać w nim jakiejś zmiany, to zostanie ona uwzględniona we wszystkich instancjach komponentu tell w naszej aplikacji. Przykładowo zwróćmy uwagę, że nasz tag a reprezentuje numer telefonu. A podajemy go tutaj w hrefie po prostu jako number. Możemy poprzedzić ten numer telefonu prefiksem tell. Dzięki temu przykładowo podczas kliknięcia w taki link na aplikacji mobilnej pojawi się od r
azu opcja zadzwonienia pod ten numer. Nasz props.tell jest numberem. Żeby połączyć go ze stringiem mamy na to kilka możliwości. Jesteśmy w klamrach, a więc znajdujemy się w javascriptowym świecie. Jeśli wpiszemy tell dwukropek plus to po zapisaniu i zinspektowaniu naszego elementu zobaczymy, że rzeczywiście teraz nasz href jest dalej numerem telefonu, ale teraz ma też odpowiedni semantyczny prefiks. A co gdybyśmy chcieli do tego celu użyć string template? No cóż, musimy tutaj całość objąć wtedy
w tyldy. Natomiast props.tell objąć w string interpolation. Jeśli zapiszemy to w takim stanie no to efekt będzie dokładnie ten sam, po prostu przekazujemy do klamer stringa, a do niego dynamiczną zmienną javascriptową props.tell, która zostaje zamieniona na numer. Możemy więc przed nią napisać teraz tell dwukropek i mamy dokładnie taki sam efekt jak przed chwilą. Komponenty pozwalają nam więc oddzielać poszczególne części naszych aplikacji. Dzięki temu możemy pracować na mniejszych reużywalnych
częściach kodu. Jeden z komponentów widzieliśmy już wcześniej, na samym starcie naszego kursu. Do funkcji render przekazywaliśmy komponent app. Jak widzimy był on owinięty w react strict mode. Niestety strict mode to dość zaawansowana koncepcja dlatego nie będziemy jej omawiać w tym filmie. Oczywiście w naszym kursie zrozumieć react pochylamy się na strict mode i tłumaczymy dokładnie jak działa. W tym filmie na youtubie pominiemy go, bo chcemy się skupić na ustawieniu pierwszych kroków w react.
Wróćmy więc do komponentu app. W pliku main.jsx zaimportujmy go ponownie. Zwróćmy uwagę, że musimy tutaj skorzystać z default importu, bo app jest zazwyczaj eksportowany jako default export. Jeśli nie wiesz czym różni się default export od named exportu to koniecznie sprawdź nasz link w opisie. dodatkowy film na ten temat, do którego link znajdziesz w opisie. I teraz wykorzystajmy app, żeby przekazać jego instancje do metody render zamiast naszego elementu. Komponent App jest tak zwanym komponen
tem wejściowym, root komponentem aplikacji. To właśnie w nim powinniśmy dodawać pozostałe komponenty budujące całą naszą stronę. W aplikacjach, w których korzystamy tylko z Reacta, zazwyczaj będziemy mieli do czynienia tylko z jednym root komponentem. Jeśli otworzymy app, to zobaczymy, że znajduje się w nim całkiem sporo kodu. Jest to kod wygenerowany przez VIT i znalazł się tutaj jedynie w celach demonstracyjnych. Możemy więc usunąć tak naprawdę wszystkie importy. Możemy usunąć ten dziwny zapis
, którym jeszcze za chwilę się zajmiemy. I możemy usunąć też wszystkie elementy zwracane w naszym liternie i zostawić pusty fragment. Widzimy, że skutkuje to pustą stroną. W pliku main.jsx co prawda zdefiniowaliśmy elementy pokazujące dane osobowe, ale nigdzie ich nie wyświetlamy, bo do metody render przekazujemy teraz app. W naszym przypadku plik main.jsx powinien zajmować się jedynie przekazywaniem root komponentu do metody render. Dlatego od tej pory dalsze ćwiczenia będziemy przeprowadzać wł
aśnie w komponencie app. Przenieśmy więc cały nasz kod do komponentu app. Najpierw wytnijmy tworzony element h1 i instancje komponentów person.info i wklejmy go w naszym fragmencie w komponencie app. Widzimy, że brakuje nam teraz danych. A więc wracamy do main.jsx możemy pozbyć się elementu, ale musimy wyciąć dane osobowe i możemy je wkleić. No i teraz gdzie je wkleić? Uwaga, te dane są stałą, więc teoretycznie oczywiście możemy wkleić je do naszej funkcji, ale skoro te dane są stałymi i nie zmi
eniają się w trakcie działania aplikacji, to możemy też wkleić je po prostu poza funkcją app. Dodatkowo widzimy, że brakuje nam jeszcze importu person.info, więc ponownie możemy skorzystać ze skrótu ctrl plus i lub command plus i lub czasami jeśli ten skrót nie działa, to wystarczy, że skasujemy ostatnią literę, napiszemy ją na nowo, no i tutaj często też jest nam podpowiadany import, a więc klikamy enter i po zapisaniu strona się odświeża i widzimy, że wraca do normy. Przenieśliśmy więc tutaj p
o prostu nasz kod do komponentu app, który jest importowany w main.jsx i przekazywany do metody render. Oczywiście oznacza to, że teraz w pliku main.jsx możemy pozbyć się importu person.info, bo nie jest już tutaj potrzebny. A co gdybyśmy chcieli dodać teraz kolejną osobę do naszej aplikacji? Naturalnie możemy stworzyć nowy obiekt i nową instancję komponentu person.info, ale to rozwiązanie nie skaluje się najlepiej. Zazwyczaj w takich przypadkach dane wszystkich osób byłyby przetrzymywane w tabl
icy. Stwórzmy więc stałą people i przypiszmy do niej tablicę obiektów z danymi osobowymi. Teoretycznie możemy teraz wykorzystać elementy tablicy do przekazania wartości do propsów, więc jeśli zamienimy person na people0, a new person na people1, no to aplikacja wraca do normy. Ale ponownie musielibyśmy tę operację powtórzyć dla każdego obiektu w tablicy. Istnieje lepszy sposób. Pamiętajmy o tym, że do jsx-owych klamer możemy przekazać javascriptowe wartości. Oznacza to, że możemy do nich przekaz
ać tablice. Jeśli do naszego fragmentu dodalibyśmy klamry, a w nich wpisali po prostu tablicę trzech numerów 1, 2, 3, to widzimy, że pojawiają się one na stronie. Co więcej warto zwrócić uwagę, że do tablic możemy przekazać elementy jsx-owe. Jeśli obejmiemy tak 1 w span, a tak 2 w strong, to po zapisaniu widzimy, że troszeczkę się one różnią, ale dla pewności możemy jeszcze je zinspektować. I widzimy, że rzeczywiście nasze numery po kolei 1 jest objęta w span, strong jest objęty w dwójkę, a trój
ka nie jest objęta w nic, jest po prostu tekstem. Te tagi wyświetlają się obok siebie zupełnie tak, jakbyśmy wpisali je jeden po drugim. Możemy tę wiedzę wykorzystać do stworzenia tablicy elementów PersonInfo. Utwórzmy nową stałą PersonInfoElements. Przypiszmy do niej tablicę people i wywołajmy na niej metodę map. Jeśli nie wiesz jak działa metoda map, jak działa metoda filter, to koniecznie sprawdź nasz dodatkowy materiał, który znajdziesz w opisie pod fragmentem tego filmu. Map przyjmuje funkc
ję iterującą po każdym elemencie tablicy people. Nazwijmy go person. Możemy teraz zamienić go na instancję komponentu PersonInfo. Jako propsy do tego PersonInfo przekażemy kolejne pola obiektu person, po którym aktualnie iterujemy, a więc name niech będzie równe person name, tel niech będzie równe person tel, a city niech będzie równe person city. Dzięki temu PersonInfoElements to tablica, w której każdy obiekt w tablicy people został zamieniony na reactowy element. Taką tablicę elementów możemy
teraz umieścić w jsxowych klamrach i zobaczymy, że elementy zostaną dodane obok siebie, zupełnie tak jakbyśmy wpisali je ręcznie. Możemy więc pozbyć się naszych starych elementów PersonInfo, a do tablicy people możemy bardzo łatwo dodać nowy element. I zobaczymy, że jeśli teraz do tablicy people dodamy jakiś nowy obiekt z danymi osobowymi, to automatycznie pojawia się on na naszej liście, ponieważ tablica people jest mapowana na te elementy PersonInfo i właśnie to jest prawdziwa esencja pracy z
komponentami, z nowoczesnymi aplikacjami frontendowymi. Mamy jakiś zestaw danych, najczęściej pobierany z backendu i mapujemy go na elementy znajdujące się w aplikacji. I tak naprawdę okazuje się, że w ogóle nie potrzebujemy tej stałej PersonInfo elements. Samo mapowanie możemy umieścić bezpośrednio w klamrach. Po zapisaniu i odświeżeniu strony widzimy, że efekt jest dokładnie ten sam. Wywołanie people map zwraca tablicę, więc tak naprawdę po prostu przekazujemy do klamer gotową tablicę element
ów jsxowych. Widzimy jednak, że w naszym kodzie pojawia się czerwony kolor. Kiedy najedziemy na ten fragment to widzimy error. Missing key prop for element in iterator. Linter podpowiada nam, że nie dodaliśmy propsa key. Czym on jest? W dużym skrócie, jeśli w Reactie renderujemy tablicę elementów to do każdego elementu tej listy powinniśmy przekazać w propertiesie key jakiś identyfikator tego elementu, tak żeby każdy element listy mógł być odróżnialny od reszty. Nie będziemy się teraz zagłębiać
w szczegóły, ale pomaga to Reactowi dokonywać optymalizacji i unikać niepotrzebnych przerysowań aplikacji. Jest to związane z tak zwanym mechanizmem reconciliation. Nie jest to prosty temat, dlatego w kursie zrozumieć React poświęciliśmy na niego całą osobną lekcję. Gdyby elementy listy nie miały propsówki to z perspektywy Reacta wygląda to tak, że zostawili na pulpicie foldery bez nazwy. Ciężko się w nich odnaleźć, dlatego powinniśmy ułatwiać Reactowi pracę. Ale co powinniśmy przekazać do tego
propsa key? W naszym konkretnym przypadku możemy przekazać jako key numer telefonu. W końcu jest to książka adresowa. Każdy numer telefonu jest unikalny i wskazuje na konkretną osobę. Niestety nie zawsze pola obiektów zawierają unikalne informacje. W takim przypadku możemy do każdego obiektu naszej tablicy dodać pole ID i przypisać mu unikalną wartość. Zazwyczaj takie listy obiektów są pobierane z back-endu i mają już utworzone pola ID, które możemy ponownie wykorzystać. Jeśli chcemy wygenerować
ID na poziomie aplikacji front-endowej możemy na przykład skorzystać z metody crypto.random.uuid Wygeneruje to randomowe ID dla każdego z tych elementów. Ale tak jak powiedzieliśmy w naszym przypadku numery telefonów też są unikalne i też wskazują na konkretną osobę. Więc dla uproszczenia zostańmy przy numerach telefonów i pozbądźmy się tego pola ID. Widzimy, że error znika, a lista dalej działa poprawnie. Wyobraźmy sobie, że jedna z osób, na przykład Karol nie podała swojego miejsca zamieszkan
ia zostawiając dane kontaktowe. Z obiektu, który reprezentuje jego dane skasujmy pole city. Jeśli zapiszemy aplikację to zobaczymy, że w przypadku wyświetlania danych Karola mamy trochę dziwną sytuację, bo wyświetlamy napis miasto a potem nie pojawia się nic. Dzieje się tak dlatego, że dla trzeciego elementu tablicy people kiedy zwracamy instancję person info to do city przekazujemy person city czyli w przypadku Karola jest to wartość undefined bo nie mamy w ogóle takiego pola. Oznacza to, że w
person info do klamer znajdujących się po miasto dwukropek przekazujemy również wartość undefined. I jak pamiętasz przekazywanie do klamer wartości undefined, null lub boolean skutkuje wyrenderowaniem pustej zawartości. Sam napis miasto z dwukropkiem wygląda dość dziwnie. Byłoby dobrze wyświetlić całą informację o mieście tylko wtedy gdy miasto jest zdefiniowane. Z pomocą przychodzi nam tak zwany conditional rendering które tak naprawdę nie jest żadnym specjalnym mechanizmem reaktowym. Jest po p
rostu połączeniem logicznym JSX i operacji na operatorach logicznych i ifach. Umieśćmy cały nagłówek H3 z informacją o mieście w klamerach. Teoretycznie wyświetla się tak samo, ale dzięki klamerom możemy wykorzystać Javascript żeby nie pokazywać tego nagłówka gdy city jest undefined. Użyjmy do tego ternary operatora i wpiszmy jeśli props.city jest różny od undefined to wtedy chcemy wyświetlać tak H3 z informacją o tym mieście. Ale w przeciwnym wypadku nie chcemy wyświetlać nic. Więc możemy tutaj
przekazać np. 0. Bo jak wiemy wtedy nic nie wyświetli się w miejscu tych klamer jeśli przekażemy do nich 0. Dzięki temu jeśli props.city jest równe undefined to do klamer przekażemy 0. A jak dowiedzieliśmy się przed chwilą w takim przypadku nie wyrenderujemy na stronie nic. Co zresztą widzimy bo przy Karolu nie wyświetla się teraz informacja o mieście. Mało tego możemy iść jeszcze krok dalej i zamiast używać ternary operatora użyć po prostu operatora logicznego. Dla przypomnienia taki zapis a i
b oznacza że jeśli a jest wartością truthy to zwrócimy b. Jeśli a jest falsy to zwrócimy a. A więc w naszym przypadku jeśli props.city jest truthy a więc nie jest wartością undefined to zwrócimy H3 z odpowiednim napisem. Natomiast jeśli props.city jest falsy a więc np. jeśli jest undefined no to zwrócimy tutaj ten undefined do klamer więc nie wyświetli się nic. Jeśli operator logiczny sprawia Ci problem nie wiesz jak działa to ponownie nagraliśmy na jego temat specjalny odcinek. Link do niego z
najdziesz pod tą lekcją w opisie pod filmem. W każdym razie jeśli city będzie równy undefined to przekażemy do klamer undefined a jeśli będzie wartością truthy to przekażemy do klamer na główek H3. Przejdziemy teraz do mechaniki chowania i pokazywania tych danych kontaktowych na liście. Powiedzmy, że domyślnie chcielibyśmy żeby w naszym kontakcie wyświetlało się tylko imię i nazwisko a numer telefonu i miasto pojawiał się dopiero po wkliknięciu w przycisk pokaż. Dodajmy więc taki przycisk w nasz
ym komponencie person.info zaraz pod naszym imieniem. Dla lepszej widoczności możemy też dodać tag.hr po nagłówku z miastem. Oddzieli to od siebie poszczególne osoby. Będziemy musieli dodać kilka rzeczy w funkcji naszego komponentu dlatego zwróćmy nasz fragment za pomocą słowa kluczowego return i dodajmy ciało funkcji. W domyślnym stanie aplikacji chcemy żeby H3 się nie pojawiały. Możemy więc wprowadzić do komponentu zmienną isExpanded reprezentującą stan danego person.info. Jeśli jest expanded
no to chcemy pokazać te szczegóły jeśli nie jest expanded to chcemy je schować a więc na początku ustawmy isExpanded na false. Możemy teraz skorzystać z conditional renderingu wytnijmy elementy z informacjami o telefonie i mieście a w ich miejscach dodajmy klamry. Następnie w klamrach skorzystajmy z operatora logicznego i wpiszmy isExpanded i tutaj wklejmy nasze elementy. Ale po zapisaniu widzimy że mamy problem. Uwaga tutaj podobnie jak w przypadku zwracania elementów z komponentu do operatora
logicznego musimy przekazać tylko jeden element więc żeby naprawić ten problem wystarczy objąć nasze elementy we fragment. Po zapisaniu Prettier za nas wszystko pięknie formatuje a my zobaczmy że nasza aplikacja zaczyna działać poprawnie no bo isExpanded jest równe false a zatem z naszego operatora logicznego isExpanded równe false zwracamy pierwszą wartość czyli przekazujemy do klamer false przez co nie wyświetla się nic. Ale jeśli zmienimy isExpanded na true to widzimy że teraz isExpanded jest
równe true a więc z operatora logicznego zwracamy drugą wartość czyli nasz fragment z elementami i wszystko wraca do normy. Tak jak powiedzieliśmy domyślnie chcemy schować te szczegóły i pokazać je po kliknięciu w przycisk wracamy więc do isExpanded false i teraz jedno z najważniejszych reaktowych pytań. Jak zmienić wartość tej zmiennej po kliknięciu w przycisk button Cóż jeśli znasz już javascript ale jest to twój pierwszy tutorial reacta to być może do głowy przychodzi ci następujący pomysł m
ożemy dodać event listener do elementu button i wywołać funkcję która zaktualizuje isExpanded na true. Jeśli odświeżymy aplikację to niestety przestaje ona działać. Sprawdźmy konsolę. Pojawia się w niej error cannot read properties of null reading at event listener co oznacza że w dokumencie nie ma elementu button i jeśli chcemy uparcie trzymać się utartych frontendowych metod to być może pomyślimy no tak ma to sens w końcu element tworzymy dopiero później w returnie. Nic dziwnego że query selec
tor go nie znalazł ale jeśli spróbujemy wyciągnąć button do stałej definiować go przed at event listenerem i dodać do timer to po zapisaniu i odświeżeniu strony widzimy że query selector znowu nie znalazł buttona. Dlaczego tak się dzieje? W momencie wywoływania funkcji person info zwracamy poszczególne elementy. Warto jednak zwrócić uwagę że są to elementy reactowe czyli zwykłe obiekty które widzieliśmy we wcześniejszej części tego filmu. Nie są to jeszcze elementy drzewa dom. Proces tworzenia e
lementów reactowych i tworzenia ich z komponentów nazywamy renderowaniem reactowym. Osobiście uważam że ta nazwa jest bardzo nieszczęśliwa ponieważ wiele osób myli ją z takim klasycznym renderowaniem drzewa dom. Tak stworzone elementy reactowe dopiero później zostają wstrzyknięte do drzewa dom za pomocą biblioteki react-dom. Proces ten nazywamy dom commit. Zrozumienie całego procesu renderowania dom commit i tego jak react wprowadza zmiany w drzewie dom to naprawdę kompleksowy temat więc w tym f
ilmie nie będziemy się w niego zagłębiać. Ale tak jak już wspomniałem w kursie zrozumieć react stawiamy jednak bardzo duży nacisk na wyjaśnienie tych tematów. Ich zrozumienie bardzo ułatwia dalszą pracę z reactem i pozwala zabłysnąć na tle konkurencji. Na potrzeby tego filmu musimy po prostu zrozumieć że w momencie wywołania funkcji komponentu tworzony element jeszcze nie znajduje się w domie. Jak więc przypiąć do niego event listener tak żebyśmy mogli odpowiedzieć na kliknięcie. React pozwala n
am na dodanie do elementów tak zwanych event handlerów. Możemy o nich pomyśleć w zasadzie jak o propsach ale takich propsach, które są już zdefiniowane przez reacta. W propsach tych przekazujemy funkcje, które będą się miały wywołać w odpowiednim momencie. Przykładowo jeśli chcemy wywołać jakąś funkcję w momencie kliknięcia na danym elemencie to do tego elementu w naszym przypadku do batona dodajemy event handler on click. I zupełnie tak jak w propsie wpisujemy jego nazwę wpisujemy równa się i p
odajemy jego wartość w klamrach. I tutaj przekazujemy definicję funkcji, którą chcemy wywołać. Możemy więc skopiować tę funkcję, którą mieliśmy w add event listenerze i wkleić ją tutaj. Wygląda to dość dziwnie prawda? Zwłaszcza że kiedy podczas eksperymentów z klamrami próbowaliśmy dodać w nich funkcje to aplikacja pokazała error. Cóż różnica jest taka, że wtedy próbowaliśmy użyć klamer do wyświetlenia treści w komponencie. Tutaj w klamrach przekazujemy definicję funkcji i podajemy ją do event h
andlera on click. Jest to specjalny mechanizm reactowy, dzięki któremu funkcja przekazana w klamrach wywoła się po kliknięciu na element baton. On click Można podpiąć do wszystkich elementów takich jak batony, tagi, a czy nawet zwykłe divy. Na starcie przygody z reactem polecam w uproszczeniu myśleć o nich tak, jak o zwykłych jsowych add event listenerach przypiętych do konkretnego elementu. Zobaczcie, w klasycznym podejściu najpierw wybieramy element. Tutaj element mamy już gotowy, bo zdefiniow
aliśmy go w jsx. Następnie przypinamy do niego odpowiedni event listener. W jsx i w react robimy to poprzez wpisanie nazwy odpowiedniego event handlera. Pozostaje jedynie jeszcze dodać funkcję, która wywoła się w momencie danego eventu. W klasycznym podejściu podajemy ją jako drugi argument add event listenera. Natomiast w reactie przekazujemy ją w klamrach tak, jakbyśmy ją przekazywali za pomocą propsów. Z biegiem filmu poznamy też inne event handlery, ale na razie zostajemy tylko przy on click
. Możemy więc skasować nasz javascriptowy add event listener, zapisać kod i widzimy, że po odświeżeniu errory znikają, aplikacja wraca do normy. Jeśli teraz klikniemy w pokaż, no to uwaga, dalej nic się nie dzieje. Nie ma żadnego efektu. Sprawdźmy dla pewności, czy nasza funkcja na pewno się wywołuje i dodajmy w niej alert. Teraz po kliknięciu, no widzimy, że alert się pojawia, więc rzeczywiście event handler działa poprawnie. Funkcja podana do on clicka wywołuje się. Aktualizujemy więc isExpand
ed do true. Dlaczego więc nasze szczegóły dalej nie są pokazane? W końcu skoro isExpanded jest równe true, no to powinniśmy zwrócić z tego operatora logicznego fragment. Cóż, elementy, które stworzyliśmy przy pierwszym renderze aplikacji zostały wyrenderowane na bazie wartości isExpanded równej false. Dlatego po pierwszym renderze, po odświeżeniu nie widzimy naszych szczegółów. Problem w tym, że nawet jeśli klikniemy button i zmienimy wartość isExpanded na true, to komponent nie zostanie ponowni
e wyrenderowany. isExpanded to zwykła javascriptowa wartość. Jej aktualizacja nie wywołuje aktualizacji komponentu. Jak sprawić, żeby komponent wyrenderował się ponownie po zmianie wartości isExpanded? Musimy przypisać tę wartość do specjalnego reactowego mechanizmu, zwanego functionem. Jeśli chodzi o stan reactowy to dużo prościej wytłumaczyć go na konkretnym przykładzie. W naszym komponencie zaimportujemy z paczki reacta specjalną funkcję useState. W funkcji personInfo w miejscu, w którym defi
niujemy isExpanded wpiszmy isExpanded równa się i tutaj wywołajmy useState i jako argument przekażmy wartość false. Wywołując useState przekazujemy do niego wartość domyślną naszej zmiennej. W naszym przypadku false. Dzięki temu dodajemy do naszego komponentu tak zwaną zmienną stanową. Czym różni się od zwykłej zmiennej? Po pierwsze wartość zwracana z useState to tablica. Zmieńmy więc nazwę zmiennej na state array. Jej pierwszy element to aktualna wartość zmiennej stanowej. Przy pierwszym render
ze jej wartość będzie równa wartości początkowej, którą przekazaliśmy do useState. Możemy więc napisać poniżej, że isExpanded jest równe pierwszemu elementowi tablicy state array. Widzimy, że po zapisaniu aplikacja dalej wygląda tak samo. Co prawda isExpanded jest teraz pobierane z wartości zmiennej stanowej, ale dalej ma wartość false, więc nie widzimy szczegółów kontaktów. Jeśli zmienimy przekazaną wartość useState na true, to po zapisaniu aplikacja pokazuje szczegóły kontaktów. Wróćmy więc do
wartości false. Kiedy klikamy w przycisk pokaż, to alert dalej się wywołuje, ale niestety isExpanded dalej nie zmienia swojej wartości. Żeby wywołać ponowny render komponentu musimy zmienić wartość zmiennej stanowej za pomocą specjalnej funkcji aktualizującej. Skąd możemy ją wziąć? Okazuje się, że jest to drugi element tablicy zwracanej z useState. Możemy więc stworzyć nową zmienną i nazwać ją setIsExpanded. Przypisujemy do niej drugi element tablicy stateArray. Następnie w naszej funkcji przyp
iętej do onClick zamiast nadpisywać wartość isExpanded wywołujemy setIsExpanded i tutaj podajemy nową wartość, którą chcemy ustawić dla tej zmiennej stanowej, czyli w naszym przypadku chcemy ustawić isExpanded na true. Zapisujemy pliki dla pewności możemy odświeżyć aplikację. Klikamy pokaż alert się wyświetla i co więcej pokazują się również szczegóły naszych elementów. Możemy więc pozbyć się tego alerta zapisać aplikację, odświeżyć ją i zobaczymy, że tak naprawdę przycisk działa dla każdego z k
omponentów osobno. Kiedy klikamy w baton wywołujemy set isExpanded true. Dzięki temu dochodzi do ponownego rendera komponentu. Tym razem jednak wartość zwrócona z useState jest zaktualizowana. Kiedy pobieramy tę wartość i przypisujemy ją do isExpanded to przypisujemy do niej wartość true. Ponownie tworzymy reactowe elementy, ale tym razem z widocznymi szczegółami kontaktu. Zmiany zostają dodane do drzewa dom i widzimy je w aplikacji. Warto zapamiętać, że kolejne rendery są po prostu wywołaniem f
unkcji naszego komponentu. Wartości zmiennych stanowych utworzonych za pomocą useState są przetrzymywane pomiędzy kolejnymi wywołaniami funkcji. Możemy o tym pomyśleć, że React przetrzymuje zmienne stanowe w swojej wewnętrznej pamięci. Możemy nieco usprawnić naszą aplikację. Widzimy, że po kliknięciu w pokaż szczegóły pojawiają się, ale przycisk dalej jest widoczny na stronie. Możemy na przykład schować go, gdy detale są widoczne. Wystarczy, że skorzystamy z conditional renderingu i użyjemy pono
wnie zmiennej isExpanded. Jeśli isExpanded jest false, to wtedy pokazujemy button. Jeśli jest true, to wtedy button chowamy. Jeśli teraz zapiszę plik, to zwróć uwagę, że strona odświeżyła się automatycznie, elementy się pokazały, a przycisk zniknął. Dlaczego się tak dzieje? No cóż, jest to związane ze specyfiką vid i tą technologią hotmodule replacement, o której wspominaliśmy. Podmieniają się pliki źródłowe, ale strona się nie odświeża. Oznacza to, że stan aplikacji, który mieliśmy przed zapisa
niem pliku, również dalej pozostaje na stronie. I jako, że nasz stan aplikacji składał się ze zmiennej stanowej isExpanded, której wartość była true, czyli mówiąc krótko, szczegóły naszych elementów były otworzone, to ten stan przechował się po zapisaniu pliku. Podmieniliśmy jednak zwracane elementy. I skoro isExpanded było true, no to schowaliśmy nasz button. Zdaję sobie sprawę, że to może brzmieć dość skomplikowanie, ale bez obaw. Po prostu chciałem podkreślić, że czasami po zapisie pliku może
sz zobaczyć swoją aplikację w trochę dziwnym stanie. Dlatego zawsze dla pewności, jeśli masz jakieś wątpliwości, wystarczy odświeżyć stronę i wtedy wracamy do początkowego stanu z domyślnymi wartościami ustawionymi w zmiennych stanowych. Także nasz state array teraz reprezentuje zmienną stanową z domyślną wartością false. Kiedy teraz kliknę pokaż na przykład na pierwszym elemencie, no to widzimy, że szczegóły się pokazują, a button się chowa. Warto zwrócić uwagę, że każda instancja komponentu ma
swój osobny stan. To znaczy dla pierwszego elementu isExpanded jest równe w tym momencie true, a dla drugiego i trzeciego to dalej jest false. Jeśli teraz zmienię isExpanded w trzecim komponencie, no to oczywiście tak samo szczegóły w nim się pokazują, a przycisk się chowa. Ale zamiast schowania przycisku możemy zmienić przycisk pokaż na schowaj, a więc skasujmy ten conditional rendering, zostawmy tutaj button element tak jak mieliśmy to przed chwilą. No i teraz w button element ponownie wykorz
ystajmy conditional rendering, ale nie musimy tutaj tworzyć dwóch różnych buttonów. Wystarczy, że zmienimy treść buttonu, z którego już korzystamy. Zobaczmy, że w tym elemencie i w tej funkcji, którą przekazujemy, mamy tak naprawdę dostęp do wszystkich zmiennych stworzonych w skopie tej funkcji PersonInfo, a więc mamy też dostęp do isExpanded. Jeśli isExpanded jest równe true, czyli button jest otworzony, to chcemy wyświetlać napis schowaj. Jeśli isExpanded jest false, to chcemy wyświetlać napis
pokaż. Możemy więc w klamrach dodać prosty ternary operator i napisać isExpanded. Jeśli isExpanded to schowaj. A w przeciwnym wypadku pokaż. I widzimy po zapisaniu plików, że ponownie strona podmieniła aktualny kod, ale stan został ten sam, a więc dla pierwszego elementu mamy otwarte szczegóły, przez co przycisk zmienił się na schowaj. Dla drugiego elementu szczegóły są schowane, więc przycisk mamy pokaż, tak że nasz ternary operator działa jak najbardziej poprawnie. No ale jeśli teraz klikniem
y przycisk schowaj, to niestety detale się nie chowają. Przycisk pokaż działa, ale chowanie nie działa poprawnie, dlatego otwierzmy stronę i spróbujmy to naprawić. Problem leży w funkcji przekazanej do onClick. Wywołujemy zawsze set isExpanded true. Oznacza to, że każde kliknięcie aktualizuje tę zmienną na true, niezależnie od tego czy wcześniej miała wartość true czy false. Żeby poprawnie obsłużyć oba przypadki, możemy do isExpanded przekazać zaprzeczenie isExpanded. Przypiszemy więc do niej wa
rtość przeciwną do aktualnej. Jeśli isExpanded było false, to ustawimy ją na true, jeśli było true, to ustawimy ją na false. Po zapisaniu i kliknięciu w przycisk pokaż, pokazywanie dalej działa poprawnie, ale dodatkowo, kiedy klikniemy w schowaj, no to chowanie też zaczyna teraz działać. W każdym komponencie możemy tworzyć tyle zmiennych stanowych, ile mamy ochotę. Ich wartościami mogą być nie tylko booliny, ale również numbery, stringi, a nawet obiekty i tablice. Na początku pracy z Reactem use
State potrafi przysporzyć naprawdę sporo problemów. Zachęcam cię do spauzowania wideo i poeksperymentowania z useState i zmiennymi stanowymi. Dodatkowo na naszym kanale znajdziesz też film, który jest darmową lekcją z naszego kursu. Tłumaczymy w nim dokładnie działanie useState. Zachęcam do sprawdzenia tego filmu po obejrzeniu naszego minikursu do końca. A tymczasem przejdźmy już do ostatniego feature'a w naszej aplikacji, czyli dodawania nowych kontaktów. Będziemy potrzebowali formularza. Dodaj
my więc w folderze Components nowy komponent Form. W pliku Form.jsx zdefiniujmy i wyeksportujmy na razie funkcję Form zwracającą prosty statyczny formularz. Przejdźmy teraz do pliku App.jsx i dodajmy go pod naszym tagiem h1. Widzimy, że wyświetla się poprawnie na stronie. Żeby przećwiczyć korzystanie z useState wprowadźmy następującą logikę. Niech ten formularz domyślnie będzie schowany. Dodajmy baton, którego kliknięcie spowoduje pokazanie tego formularza. Nazwijmy ten baton dodaj. W komponenci
e App podobnie jak w komponencie PersonInfo stwórzmy zmienną stanową, która będzie wskazywała na to czy formularz jest widoczny czy nie. Na początku chcemy, żeby była równa false. Spisujemy więc const state array i wywołujemy useState. Oczywiście musimy je zaimportować z Reacta i do useState przekazujemy domyślną wartość. Tak jak powiedzieliśmy niech będzie to false. I oczywiście możemy tutaj stworzyć zmienną stanową, nazwać ją as form shown i wyciągnąć pierwszy element tablicy state array, ale
możemy też skorzystać z destructuringu. Jeśli nie wiesz czym jest destructuring to mamy specjalny odcinek na ten temat. Link do niego znajdziesz w opisie pod tym fragmentem filmu, ale w dużym skrócie. Zamiast wyciągać pierwszy i drugi element z tablicy state array możemy je zdefiniować od razu zapisując const, tworzymy tablicę i pierwszy element tej tablicy nazywamy as form shown, a drugi set as form shown. Dzięki temu tworzymy dwie stałe. As form shown przyjmie wartość pierwszego elementu tabli
cy zwróconej z wywołania useState, a set as form shown przyjmie wartość drugiego elementu tablicy zwróconej z wywołania useState. Możemy teraz wykorzystać as form shown w połączeniu z conditional renderingiem po to żeby wyświetlić instancje komponentów form, a więc wycinamy ją, dodajemy klamry, wpisujemy as form shown i podajemy tutaj form. I widzimy że as form shown jest pobierane poprawnie, bo formularz zniknął z naszej strony. Dodajmy teraz do batona aktualizację zmiennej stanowej as form sho
wn, a więc w momencie kliknięcia na baton, czyli onClick przekazujemy tutaj funkcję i wywołujemy set as form shown i jako wartość podajemy tutaj true, no bo chcemy żeby nasza zmienna stanowa as form shown przyjęła teraz wartość true. Zapiszmy nasze pliki i spróbujmy teraz kliknąć przycisk dodaj i widzimy że po kliknięciu as form shown zmienia wartość na true, więc komponent formularza się pokazuje. I tutaj przy okazji przekazywania funkcji do event handlerów bardzo ważne jest, żeby pamiętać o ty
m, że przekazujemy tutaj całą definicję funkcji. Nie możemy tutaj przekazać samego wywołania set as form shown, bo to niestety wywali aplikację. Pamiętajmy, przekazujemy do onClick funkcję, która ma się wywołać w momencie kliknięcia, a więc musi to być pełnoprawna definicja. Dodatkowo warto wspomnieć, że taką funkcję i każdą inną przypinaną do event handlerów możemy wynieść do osobnej definicji w komponencie, więc jeśli ją wytnę i stworzę nową stałą, na przykład nazwaną handle show form click i
przypiszę do niej wyciętą definicję funkcji, to mogę się teraz do tej definicji odwołać bezpośrednio wpisując tutaj handle show form click. No i teraz widzimy, że po kliknięciu w przycisk dodaj Aplikacja działa dokładnie tak samo, bo w momencie kliknięcia wywołujemy funkcję handle show form click, którą mamy zdefiniowaną troszkę wyżej. Więc w przypadku prostych komponentów wpisywanie funkcji bezpośrednio w tych event handlerach jest jak najbardziej ok, no ale czasami tych event handlerów mamy sp
oro i ta część zwracana z komponentu zwana potocznie widokiem potrafi się bardzo rozrosnąć. Dlatego powszechną praktyką jest też wyciąganie tych funkcji przekazywanych do event handlerów do osobnych stałych. I tutaj jeszcze raz podkreślmy, że musi to być sama definicja funkcji, która zostanie wywołana w momencie kliknięcia. Nie możemy więc tutaj wywołać handle show form click, no bo wywołanie handle show form click zwraca undefined, więc to zachowuje się tak jakbyśmy do onclick przekazali undefi
ned, więc trzeba tego pilnować, ale po jakimś czasie zaczyna to być naprawdę bardzo intuicyjne. Także nasz formularz pojawia się poprawnie. Możemy schować baton dodaj w momencie, gdy isFormShown jest równe false, a więc tak naprawdę całe to wyrażenie w klamrach możemy zamienić na ternary operator, a więc jeśli isFormShown jest równe true, to pokazujemy instancję formularza, a w przeciwnym wypadku możemy wyciąć nasz baton i wkleić go jako drugą część wyrażenia ternary operatora. Także jeśli isFor
mShown będzie false, to baton zniknie, co zresztą widzimy na naszej stronie dla pewności po odświeżeniu, kiedy klikamy w dodaj, to formularz się pojawia, a baton znika. A więc przejdźmy do stworzenia odpowiednich pól formularza. W komponencie form będziemy chcieli umieścić trzy inputy. Pierwszy na imię, obejmijmy go więc w diva i jako name przekażmy tutaj name, przekażmy też placeholder i taki input na nasze potrzeby jak najbardziej wystarczy. Następnie potrzebujemy inputa dla numeru telefonu, w
ięc ponownie dodajemy diva, a w środku input type zmieńmy na tel, name ustawmy na tel i jako placeholder wpiszmy telefon. I pozostał nam trzeci input na miasto, a więc dodajemy ostatniego diva, wpisujemy input i to też będzie type text, jako name ustawiamy city, a jako placeholder wpisujemy miasto. Będziemy też potrzebowali batona, żeby wysłać ten formularz, a więc dodajmy baton, a w jego treści wpiszmy zapisz. Formularz mamy gotowy, więc jeśli zaczniemy tutaj wpisywać rzeczy, to pojawiają się o
ne poprawnie, ale jak właściwie obsłużyć zapisanie danych z tego formularza? No moglibyśmy dodać onclick na naszym batonie, ale onclick to nie jest jedyny dostępny event handler. Na wiele eventów znanych nam z klasycznego javascriptu przypada odpowiedni handler reactowy. Przykładowo mouseenter to onmouseenter, a submit to onsubmit. Możemy więc dodać do naszego formularza onsubmit. Kiedy dodamy w klamrach definicję funkcji i dla testu użyjemy w niej console.loga, to kiedy otworzymy nasze deptulsy
i spróbujemy wysłać formularz, to niestety w konsoli nie pojawia się nic. Dodatkowo jeśli zwrócimy uwagę na ikonę w pasku przeglądarki, to zobaczymy, że strona się odświeża. Dzieje się tak dlatego, że domyślnym zachowaniem po evencie submit jest właśnie przekierowanie strony. Możemy zablokować to zachowanie korzystając z eventu przekazywanego podczas wysyłania formularza. Podczas wywoływania eventów przeglądarkowych funkcje, które definiujemy w eventach otrzymują specjalny obiekt reprezentujący
dane zdarzenie. Nie jest to specyfika dla Reacta. To samo zachowanie powinniśmy znać już z obsługiwania zwykłych eventów javascriptowych. Oczywiście jako, że jest to parametr funkcji to możemy go nazwać dowolnie, jednak zwyczajowo nazywamy go event albo po prostu w skrócie e. A więc jeśli w naszej funkcji przekazanej do onSubmit sparametryzujemy sobie ten event nazwiemy go e, to teraz w funkcji możemy wywołać e prevent default. Zapiszmy teraz nasz kod, spróbujmy dodać nowe dane i teraz zapiszmy
formularz i widzimy, że nie dochodzi do przekierowania strony, a w konsoli wyświetla się informacja formularz wysłany. Ale jak w tym momencie dodać dane z formularza do naszej listy osób? Na początku spróbujmy po prostu wyświetlić dane formularza w konsoli w momencie, w którym klikamy na przycisk. Sposobów na to jest bardzo dużo, ale skupimy się na najbardziej popularnym i zalecanym zwanym kontrolowanymi inputami. Głównym założeniem jest to, że do każdego pola formularza przypiszemy zmienną sta
nową. Zacznijmy od imienia i nazwiska. Stwórzmy za pomocą useState zmienną stanową name i od razu określmy też jej funkcję aktualizującą. Jak pewnie widzisz, popularnym patternem jest nazywanie funkcji aktualizującej poprzedzając po prostu nazwę zmiennej stanowej słowem set. Także dla name mamy set name i przypisujemy do tego wywołanie useState. Oczywiście useState należy zaimportować z Reacta i jako wartość domyślną przekazujemy na początku pusty string. Możemy teraz dodać tę wartość name jako
default value dla naszego inputa reprezentującego name. Dzięki temu, gdybyśmy teraz z jakiegoś powodu chcieli ustawić tutaj domyślną wartość, to po odświeżeniu aplikacji ten input zawsze domyślną wartość będzie miał ustawioną, zsynchronizowaną z naszą zmienną stanową. No ale wróćmy tutaj do domyślnej wartości pustego stringa. Teraz najtrudniejsza część. Musimy zaktualizować tę zmienną stanową w momencie zmiany wartości inputa. W zwykłym javascriptie do obsługi inputów najczęściej korzystamy z ev
entu change. No a w Reactie możemy to osiągnąć dzięki event handlerowi onChange. Do inputa dodajmy więc onChange i w klamrach przekażmy anonimową funkcję. Podobnie jak w przypadku onSubmit funkcja ta przyjmuje event. Jeśli skonsologujemy ten event, to w momencie wprowadzenia jakiejś zmiany w inpucie name, na przykład wpisania dowolnej litery, to zobaczymy w konsoli synthetic base event. Nie jest to zwykły event znany nam z addEventListeners, tylko event wzbogacony nieco przez React. Nie musimy t
utaj wchodzić w szczegóły. Na nasze potrzeby możemy traktować go jak każdy inny event. Jeśli go rozwiniemy to zobaczymy, że tak jak w przypadku zwykłych eventów, mamy dostęp do target. Reprezentującego element, który dany event wywołał. W naszym wypadku jest to input znajdujący się na stronie. Oznacza to, że target wskazuje na nasz input. Możemy więc pobrać jego value i przekazać je do funkcji aktualizującej zmienną stanową name. W onChange wpisujemy więc setName, a jako wartość przekazujemy tut
aj event.target, to wskazuje na nasz input i wybieramy z targetu jego value. Zapisujemy zmiany. Dzięki temu w momencie, w którym zmienimy wartość inputa, to wywoła się funkcja onChange. Zaktualizuje ona wartość name i ponownie wyrenderuje komponent. Wartość name będzie już wtedy zaktualizowana, więc do inputa przekażemy nowe value. W funkcji podanej do onSubmit możemy teraz skonsologować wartość zmiennych stanowych. A więc zamiast konsologować formularz wysłany, skorzystajmy tutaj z destructurin
gu, żeby skonsologować wartość name. Otwórzmy naszą konsolę, dla pewności odświeżmy stronę. Otwórzmy formularz i spróbujmy wpisać tutaj jakieś imię. I teraz wysłać formularz. I widzimy, że w konsoli pojawia się obiekt o polu name z wartością Filip. Tworzymy najpierw instancję komponentu ze zmienną stanową name. Ta wartość zmiennej stanowej jest przekazana do inputa. W momencie zmiany wartości inputa, zmienną stanową aktualizujemy, przypisując do niej aktualną wartość inputa. Dzięki temu w momenc
ie submitowania tego formularza, czyli wywołania tej funkcji przekazanej do onSubmit, jeśli odczytamy wartość zmiennej stanowej name, no to będzie ona już tą zaktualizowaną wartością. Tworzymy więc pewnego rodzaju synchronizację pomiędzy zmienną stanową a elementem input. Ale zdaję sobie sprawę, że wygląda to dość skomplikowanie. Co właściwie daje nam takie podejście i kontrolowanie inputów? Czy nie moglibyśmy używać po prostu inputów i formularzy, które przesyłają eventy w klasyczny sposób? Mog
libyśmy, ale dzięki temu, że ich wartości przetrzymujemy w zmiennych stanowych, to dużo prościej wykorzystać je w innych częściach komponentu. Przykładowo, powiedzmy, że chcielibyśmy, żeby nasz button był w stanie disabled, jeśli użytkownik nie wypełnił jeszcze wymaganych danych. W button dodajmy atrybut disabled. Jeśli wpiszemy równa się i ustawimy disabled na true, no to element będzie taki wyszarzony. A więc możemy tę wartość obliczyć wpisując tutaj klamry i chcemy, żeby disabled było w momen
cie, gdy nie mamy jeszcze wypełnionych wartości dla imienia. Możemy więc tutaj wpisać name length równe zero. A więc kiedy wartość imienia będzie pusta, no to wtedy button powinien być w stanie disabled. I jeśli zapiszemy nasze pliki i odświeżymy stronę, otworzymy formularz, to rzeczywiście zwróćmy uwagę, że na początku nasz button jest disabled. Wartość zmiennej stanowej to pusty string. No więc oczywiście jej długość jest równa zero, przez co disabled przyjmuje wartość true. Ale kiedy tylko wp
iszemy dowolną literę, to aktualizujemy wartość tej zmiennej stanowej. Dzięki czemu disabled ma teraz wartość false, no bo name ma już długość jeden. A więc w tym momencie możemy wysłać formularz. I jest to prawdziwa potęga reacta i zarządzania stanem. Zamiast ciągle odczytywać wartości z drzewa dom za pomocą document query selector, trzymamy nasz stan w jednym miejscu i konsekwentnie aktualizujemy go w wyniku akcji użytkownika. To podejście jest dużo bardziej skalowalne od klasycznego, imperaty
wnego manipulowania stronami i aplikacjami. Name działa. Spróbuj teraz spauzować wideo i samodzielnie dodać obsługę phone i city. Możemy od razu stworzyć dwie zmienne stanowe. Pamiętajmy, nie ma limitu, jeśli chodzi o liczbę zmiennych stanowych w komponencie. A więc wpisujemy const tel i set tel. Równe, wywołujemy use state. I jako wartość domyślną również przekazujemy pusty string. Następnie tworzymy city i set city. I tutaj również przekazujemy pusty string jako wartość domyślną. Ich wartości
przekazujemy jako default value do inputów. A więc dla inputu tel przekazujemy default value. Równe, zmienna stanowa tel. A dla inputa city przekazujemy default value. Równe, zmienna stanowa city. Zapisujemy kod. Prettier za nas wszystko pięknie formatuje. No i pozostaje nam dodać obsługę zmiany tych eventów. A więc podobnie jak dla pierwszego z inputów. Dodajemy on change w naszym inpucie tel. I w klamrach przekazujemy anonimową funkcję, która odbiera event. I wywołujemy tutaj set tel, do które
go przekazujemy event target. A więc w tym przypadku będzie to input odpowiadający za telefon. No i pobieramy jego value. Zapisujemy. I dla trzeciego z inputów, inputu city, robimy dokładnie to samo. Z tym, że tutaj wywołujemy set city. Po to, żeby zaktualizować wartość zmiennej stanowej city. Możemy też w atrybucie disabled dla batona, dodać warunek na nie pustą wartość fon. A więc chcemy, żeby baton był disabled, jeśli name length jest równe 0. Albo tel length jest równe 0. Zobaczmy, że teraz
żeby aktywować ten baton, musimy wypełnić nie tylko imię, ale również telefon. Jeśli chodzi o city, to jak pamiętamy, nie jest on konieczny do wyświetlania informacji o danej osobie. Jeśli dodamy wartości tel i city w naszym console.logu wywoływanym w momencie submitowania formularza, to po zapisaniu i wypełnieniu formularza do końca, widzimy, że w konsoli pojawia się piękny obiekt z danymi odpowiadającymi danym formularza. Jak teraz dodać taki obiekt z danymi do naszej tablicy osób? Tablica ta
znajduje się w komponencie app. Musimy więc zapewnić komunikację pomiędzy app a komponentem form. Jak pamiętamy, do komunikacji możemy wykorzystać propsy. Do tej pory dowiedzieliśmy się, że w propsach możemy przekazywać proste wartości, takie jak string czy boolean. Ale okazuje się, że w propsach możemy również przekazywać definicję funkcji. W komponencie app zdefiniujmy funkcję addPerson. Na razie w celach testowych wywołajmy w niej po prostu console.log. Funkcję tę przekażmy do komponentu form
jako props. Nazwijmy go onAddPerson. Tutaj staramy się zachować konwencję nazewnictwa związaną z event handlerami. Oczywiście onAddPerson to funkcja, która będzie wskazywać konwencję nazewnictwa związaną z event handlerami. Oczywiście onAddPerson to nie jest natywny event wspierany przez Reacta. To po prostu props stworzony przez nas. Ale dzięki nazwaniu go onAddPerson wskażemy, że będziemy tutaj chcieli prawdopodobnie przekazać funkcję, która zostanie wywołana w momencie dodania osoby w danym
formularzu. W komponencie form możemy teraz zdefiniować propsy. Props onAddPerson jest więc funkcją Jeśli wywołamy ją w funkcji onSubmit, to po wysłaniu formularza, rzeczywiście w konsoli pojawia się również napis addPerson. Pomimo tego, że funkcja jest zdefiniowana w app, to dzięki propsom jesteśmy ją w stanie wywołać w form. Przy okazji możemy skorzystać z bardzo popularnego patternu i zastosować destructuringPattern. podczas definiowania propsów. Skoro props to obiekt z polem onAdPerson możem
y w parametrach funkcji bezpośrednio wyciągnąć z tego obiektu onAdPerson. Dzięki temu nie musimy już odwoływać się do props onAdPerson wystarczy nam sama nazwa tej zmiennej którą otworzyliśmy czyli onAdPerson. Ponownie przypominam, że jeśli nie wiesz jak działa destructuring to w opisie pod tym fragmentem lekcji znajdziesz link do naszego materiału bonusowego, który tłumaczy to zagadnienie. Spróbujmy teraz pójść o krok dalej i przekazać nasz obiekt z danymi do funkcji onAdPerson. Pozbądźmy się c
onsole.loga zapiszmy nasz kod i spróbujmy wywołać formularz. No cóż, widzimy, że funkcja wywołuje się poprawnie, bo w konsoli pojawia się onAdPerson. Niestety nie pojawia się zestaw naszych danych. Dzieje się tak dlatego, że co prawda przekazujemy do onAdPerson zestaw danych, ale w samej definicji tej funkcji przekazanej z komponentu app nie korzystamy z niego w żaden sposób. Mało tego ta funkcja jeszcze nie przyjmuje żadnych argumentów. Musimy więc dodać do niej parametr. Nazwijmy go po prostu
data. Ten parametr możemy teraz przekazać do console.loga. I kiedy teraz spróbujemy przesłać nasz formularz to widzimy, że ponownie w naszej konsoli pojawia się zestaw danych wpisanych w formularzu. Ale jak dodać go do naszej tablicy people? Składa się ona z obiektów o polach name, tell i city. Jeśli spróbujemy w onAdPerson wywołać po prostu people push data to po wysłaniu tego formularza niestety nie dzieje się nic. Mamy tutaj dokładnie ten sam problem, który mieliśmy podczas pokazywania szczeg
ółów w person.info. Dodanie wartości do jsowej tablicy people nie powoduje rendera. Musimy więc przetrzymać naszą tablicę w zmiennej stanowej a następnie zaktualizować ją w funkcji adPerson. Zmieńmy nazwę stałej people na initial people. Następnie stwórzmy zmienną stanową people wraz z funkcją aktualizującą set people i do useState jako wartość początkową przekażmy właśnie initial people, czyli tę tablicę, której do tej pory cały czas używaliśmy. Dzięki temu po zapisaniu aplikacji widzimy, że ap
likacja działa dokładnie tak jak działała przed chwilą. No bo po prostu wyciągnęliśmy tutaj initial people do osobnej stałej i przekształciliśmy ją na zmienną stanową. Teraz zależy nam na tym, żeby tę tablicę people przechowywaną w zmiennej stanowej zaktualizować dzięki czemu będziemy mogli wywołać render komponentu. W adPerson dodajemy już do people nowy obiekt z danymi. Jeśli teraz spróbujemy wywołać set people i podamy tutaj tablicę people no to zobaczmy co stanie się, gdy otwierzymy dla pewn
ości stronę, otworzymy formularz i spróbujemy tutaj wpisać dane. Po zapisaniu niestety dalej nie dzieje się nic. Widzimy, że lista nie została zaktualizowana. I tutaj przechodzimy do bardzo ważnego warunku działania funkcji aktualizującej. Stan aktualizuje się tylko wtedy, gdy nowa wartość zmiennej stanowej jest różna od starej. Ma to sens, skoro wartość się nie zmieniła to nie ma sensu jej aktualizować i wywoływać re-rendera. Ale przecież dodaliśmy do tablicy people nową wartość. Niestety zrobi
liśmy to za pomocą metody push. Wywołanie push nie tworzy nowej tablicy, dlatego z perspektywy Reacta people, które przekazujemy do set people to ta sama tablica people, którą React przechowuje w zmiennej stanowej. Tablice są porównywane po referencji, więc pomimo wywołania push mają tę samą wartość. Więcej o porównywaniu po referencji mówimy w naszym bonusowym materiale, który znajdziesz w opisie. Do set people chcemy więc przekazać nową tablicę, która ma wszystkie elementy people, a dodatkowo
jest zmniejszona o nowy obiekt. Możemy w tym celu skorzystać ze spread operatora, aby utworzyć nową tablicę i przekazać do niej element tablicy people. A więc wpisujemy const new people i tutaj. Tworzymy nową tablicę i dodajemy spread operator i spreadujemy w naszej tablicy wszystkie elementy tablicy people. Dzięki temu w tym momencie new people to nowa tablica, ale wszystkie jej elementy są dokładnie takie same jak elementy tablicy people. Dodatkowo po przecinku dodajemy do naszej tablicy kolej
ny obiekt reprezentujący dane osobowe, czyli nasz obiekt data przesłany z komponentu form. Pozostaje jedynie przekazać tę tablicę new people do wywołania set people. Zobaczmy co teraz się stanie. Odświeżmy stronę, zamknijmy naszą konsolę i spróbujmy dodać nową osobę. I widzimy, że nowa osoba została dodana i od razu działa dla niej cała logika pokazywania i chowania szczegółów. Ostatnim usprawnieniem, które możemy dodać jest zamknięcie formularza w momencie dodania nowej osoby, a więc funkcji ad
d person powinniśmy po prostu wywołać funkcję aktualizującą zmienną stanową set is form shown i przekazać tutaj wartość false, no bo chcemy schować nasz formularz. Otwierzmy teraz stronę. Zwróćmy uwagę, że dodana osoba nie zapisała się. Jest to spowodowane faktem, że nasza tablica istnieje tylko w naszym programie javascriptowym. Ona nie jest zapisywana nigdzie na backend, ani w naszym local storage. Oczywiście są to usprawnienia, które moglibyśmy dodać, ale tutaj chcemy się po prostu skupić na
tych podstawowych reactowych mechanikach. W kursie zrozumieć react przechodzimy zarówno przez dodawanie rzeczy do local storage, jak i przez całą współpracę z backendem, ale gdybyśmy mieli tutaj przejść w tym filmie przez to wszystko, no to on bardzo, bardzo by się wydłużył. W każdym razie, jeśli spróbujemy teraz dodać nową osobę, to po zapisaniu Jan rzeczywiście dodaje się na liście, a dodatkowo formularz się chowa. Spróbuj teraz samodzielnie dodać featury takie jak usuwanie poszczególnych kont
aktów lub edytowanie poszczególnych kontaktów. Myślę, że będzie to świetne ćwiczenie związane z reactem. A my teraz przejdziemy do stylowania. Nasza aplikacja nie grzeszy pięknością, dlatego pora ją ostylować. Jeśli chodzi o stylowanie aplikacji reactowych, to dostępnych jest wiele metod i narzędzi. My zajmiemy się tymi najprostszymi. Przejdźmy do pliku indeksa tml. Jeśli w tagu head dodamy tag style, a w nim proste style np. dla formularza, to po otwarciu formularza widzimy, że style zostają za
aplikowane. Oznacza to, że elementy tworzone za pomocą reacta podlegają takim samym regułom jak elementy tworzone za pomocą zwykłego html lub js. Jeśli do naszej strony dodamy stylę dla tagu form, to tag form utworzony za pomocą react otrzyma te style. Oczywiście możemy je wynieść do osobnego pliku i zaimportować za pomocą link i efekt będzie ten sam. Ale to rozwiązanie nie skaluje się zbyt dobrze. Trzymanie stylów dla wszystkich komponentów w jednym miejscu na dłuższą metę jest bardzo niewygodn
e. Bardzo popularnym reactowym rozwiązaniem jest importowanie stylów w plikach jsx. W javascriptie nie mamy takich możliwości. Gdybyśmy spróbowali zaimportować style w pliku js, to oczywiście nie zadziałałyby one poprawnie. Jeśli jednak zaimportujemy arkusz stylu w pliku jsx, to zostanie on dodany do strony. I jak to zrobić? Tak naprawdę widzieliśmy już tą mechanikę. Po postawieniu projektu vid w pliku main.jsx importowaliśmy plik index.css. Spróbujmy więc zaimportować ten plik w pliku main.jsx
ponownie. Wpisujemy import i podajemy ścieżkę do pliku css, a więc w naszym przypadku to jest ta indeks.css. Ponieważ indeks.css znajduje się na tym samym poziomie co main.jsx. Zwróćmy uwagę na specyfikę tego importu. Nie jest to ani named, ani default import. Po prostu wpisujemy import i po nim ścieżkę do pliku. Jeśli zapiszemy plik, to w naszej aplikacji od razu zostaną zaaplikowane style. Zerknijmy na plik indeks.css. Widzimy w nim bardzo podstawowe style. Możemy je zachować i wykorzystać jak
o bazowe style naszej strony. Jeśli zinspektujemy naszą stronę, to zobaczymy, że w tagu head pojawia się teraz dodatkowy tag style zawierający właśnie tę style z pliku indeks.css. Jest to zasługa vid. Indeks.css jest plikiem, w którym zazwyczaj umieszczamy style globalne. Między innymi dla root czy body. A co jeśli chcemy ostylować jakiś konkretny komponent? Podstawowym i bardzo popularnym rozwiązaniem jest stworzenie plików css dla każdego z komponentów i importowanie tych stylów w plikach jsx.
Okazuje się, że tę metodę również już widzieliśmy. Kiedy otworzyliśmy po raz pierwszy plik app.jsx znajdował się w nim import pliku app.css. Zerknijmy na ten plik. Zawiera on style dla kilku elementów, których pozbyliśmy się już z aplikacji. Takich jak logo. Ale zawiera on również style dla elementu o id root. Możemy je wykorzystać. Skasujmy więc wszystkie pozostałe style. I zostawmy tylko te style dla elementu o id root. Następnie zaimportujmy app.css w pliku app.jsx, więc wpisujemy tutaj impo
rt i ponownie podajemy ścieżkę do pliku ze stylami. A więc kropka u kośnik app.css. Po zapisaniu widzimy, że style dla diva o id root zostały zaaplikowane. Możemy trochę odzumować naszą aplikację, żeby lepiej widzieć całość w połączeniu z konsolą. Widzimy, że w tagu head również pojawił się kolejny arkusz stylów, tym razem dla pliku app.css. Spróbujmy oscylować naszą listę kontaktów. Najpierw obejmijmy ją w tag ul w celu zachowania poprawnej semantyki. Widzimy, że lista się nam trochę rozjechała
. Musimy teraz w app.css dodać odpowiednie style dla tagu ul, a więc wpisujemy ul padding 0 list type type none. Lista została wyrównana, więc przejdźmy teraz do oscylowania poszczególnych elementów listy. A więc chcemy dodać style dla komponentu person.info. Obok komponentu person.info stwórzmy więc plik person.info.css. Następnie zaimportujmy go w pliku person.info.jsx. Zamiast zwracać z tego komponentu fragment, możemy zwrócić tag li. Będzie to poprawne semantycznie, no bo w końcu wszystkie t
e elementy person.info teraz obejmujemy w tag ul. Możemy też pozbyć się tagu hr, bo border zaraz dodamy w css. W person.info.css dodajmy teraz style dla tagów li. Dodajmy więc najpierw border, dodajmy mu zaokrąglenie, oddzielmy trochę od siebie te komponenty i dodajmy lekki padding. Okej, nasza lista zaczyna wyglądać coraz lepiej, style aplikują się i warto zwrócić uwagę na następującą rzecz. Pomimo tego, że w naszej aplikacji mamy trzy instancje komponentu person.info to arkusz stylów dla perso
n.info zostaje dodany tylko raz. Nie musimy się więc tutaj przejmować problemami z wydajnością i dodawaniem zbyt dużej ilości kodu css do strony. Na koniec dodajmy style do naszego formularza. Utwórzmy plik form.css i zaimportujmy go w naszym pliku form.jsx. Zobaczmy jak formularz wygląda do tej pory. Musimy więc w zasadzie ostylować jedynie te inputy, a więc w pliku form.css dodajemy style dla inputa i wpisujemy tutaj margin bottom. Dodajemy też troszkę paddingu i rozszerzamy je na całą szeroko
ść rodzica. Formularz wygląda lepiej, aczkolwiek widzimy, że wychodzi on nieco poza krawędź. Możemy więc dodać w inpucie box sizing border box, albo jeśli tak jak ja po prostu wolisz używać box sizing border box na wszystkich elementach, to możesz to wyciąć i dodać w stylach globalnych. A więc w naszym pliku index.css wystarczy, że powiedzmy pod pseudo selektorem root dodasz regułę dla wszystkich elementów i tutaj określisz box sizing border box. Efekt będzie ten sam i dzięki temu wszystkie elem
enty mają teraz box sizing border box. Widzimy, że nasza aplikacja wygląda teraz znacznie lepiej. Musimy jednak zwrócić uwagę na jedną rzecz. Widzieliśmy już, że wszystkie te arkusze stylów są dodawane do tagu head na naszej stronie. Oznacza to, że niestety style mogą ze sobą wejść w kolizję. Co to znaczy? No oznacza to mniej więcej tyle. Wyobraźmy sobie, że rozbudowujemy nasz form component i dodajemy później w nim też jakąś listę i próbujemy ostylować nasze elementy li znajdujące się w tej liś
cie. Wpisujemy tutaj na przykład border color red. No i zobaczmy. Border color red został zaaplikowany do wszystkich elementów li znajdujących się w tagu ul na naszej stronie. To są po prostu zwykłe cssowe zasady. To nie jest nic specyficznego dla Reacta. Dla ułatwienia wyobraźmy sobie, że importowanie tych plików css to nic innego jak dodawanie kolejnych style tagów na stronie. Musimy więc być ostrożni z selektorami. Oczywiście zastosowanie odpowiednich i różnorakich nazw class pomaga, ale nies
tety przy większych aplikacjach czasami ciężko wymyślić unikalną nazwę i tak czy siak może dojść do takiej kolizji selektorów. Na szczęście istnieją narzędzia, które rozwiązują ten problem a dodatkowo dają nam nieco więcej możliwości jeśli chodzi o stylowanie aplikacji w React. Obecnie na rynku najpopularniejsze są trzy metody stylowania. CSS modules CSS w javascript przy użyciu bibliotek takich jak emotion lub styled components i Tailwind CSS. Metody te bardzo różnią się od siebie. Oczywiście w
kursie zrozumieć react omawiamy każdą z nich, ale tutaj nie będziemy już zagłębiać się w te szczegóły ponieważ dla takiej prostej aplikacji jak nasza importowanie plików css jest jak najbardziej wystarczające. Dodatkowo na stronie zrozumieć react.pl w sekcji lekcji demo znajdziesz darmową lekcję o CSS modules więc zachęcam do obejrzenia jej po skończeniu tego filmu. A tymczasem pozwolmy się już naszego przykładowego czerwonego koloru bordera. Bardzo często w aplikacjach chcemy pokazać różne sty
le w zależności od stanu danego komponentu. Przykładowo wyobraźmy sobie, że chcemy żeby nasz person info miał fioletowy border kiedy jest expanded. Jak osiągnąć taki cel? W klasycznym javascriptie z reguły dodajemy na przykład style dla klasy active a następnie dodajemy tę klasę do elementu w odpowiednim momencie. W person info dodajmy więc style dla elementu li o klasie active. Żeby przetestować style dodajmy teraz odpowiednią klasę dla wszystkich naszych elementów li a więc wpiszmy klasa równa
się do klasy active. No i tutaj widzimy, że mamy kolor czerwony. O co tutaj chodzi? Musimy wrócić do samego początku filmu. Pamiętasz jak mówiliśmy, że wszystkie te wywołania elementów jsx-owych zostają zamienione na kod javascriptowy? Okazuje się, że słowo klas w javascriptie ma specjalne znaczenie. Być może wiesz, że jest ono używane właśnie do tworzenia javascriptowych klas. Więc żeby tutaj uniknąć konfuzji to nie możemy używać tego html'owego słowa klas. Musimy zamienić ją na nazwę atrybutu
className, co zresztą React nam podpowiada. Jeśli zamienimy klas na className, zapiszemy aplikację to widzimy, że active zostaje dodane poprawnie, bo pojawia się fioletowy kolor. Jest to dość specyficzne zachowanie dla Reacta, które dość mocno miesza wielu osobom na starcie przygody z tą biblioteką, ale po chwili łatwo jest się do tego przyzwyczaić. Klas nie jest jedynym takim przypadkiem. Przykładowo to samo dzieje się, kiedy używamy atrybutu for związanego z inputami. For też jest słowem kluc
zowym w javascriptie, dlatego kiedy używamy for w JSX, no to musimy użyć html for. Ale o tym React również nam podpowie, więc nie będziemy tutaj przechodzić przez wszystkie te edge cases, tylko skupimy się na klasie. No dobrze, mamy więc nasz className active, ale chcieliśmy, żeby on pokazał się tylko wtedy, gdy element jest expanded. Jak to zrobić? No bardzo prosto. Tak naprawdę możemy już wykorzystać do tego tę wiedzę, którą mamy. Wystarczy, że wartość className przypiszemy w klamrach, a więc
dodajemy tutaj klamry i dynamicznie obliczymy wartość, która ma się tutaj pojawiać. Jeśli jest expanded, to chcemy dodać active. Natomiast jeśli nie jest expanded, to możemy tutaj dodać pusty string. Zapisujemy kod i widzimy, że dla pewności po odświeżeniu aplikacja wraca do normy, ponieważ isExpanded dla wszystkich elementów jest false, a więc className jest puste. Ale kiedy klikniemy pokaż, no to zwróćmy uwagę, że wtedy dla pierwszego elementu isExpanded jest równe true, a więc className przyj
muje wartość stringa active. Oczywiście kiedy schowamy ten element, to isExpanded wraca na false, a więc klasa też znika. Także zdaję sobie sprawę, że dodawanie class w javascriptie to jedna z pierwszych mechanik, których uczymy się na starcie przygody z tym językiem, aczkolwiek tutaj warto też nauczyć się tego reactowego podejścia, bo pomimo, że w reactie żeby chować elementy, to nie używamy już sztuczek takich jak displayNone, tylko raczej używamy conditional renderingu, to oczywiście dodawani
e konkretnych stylów dla danego stanu komponentu bardzo się przydaje, więc warto zapamiętać, że po prostu takie nazwy class możemy również wyliczać jako zwykłe wartości javascriptowe i przekazywać je do Clamor. No dobrze, nasza aplikacja jest już mniej więcej gotowa, pora wrzucić ją do internetu. Do tej pory cały czas pracowaliśmy na naszej aplikacji lokalnie, widzieliśmy wszystkie wprowadzone zmiany od razu i byliśmy w stanie łatwo podglądać co się w niej dzieje, ale jak wrzucić taką aplikację
do internetu? Teraz zobaczymy jak wrzucić taką aplikację do internetu jako statyczną stronę. Możemy przerwać nasz proces dev i wpisać komentę npm run build. Po zakończeniu komendy widzimy, że w naszym projekcie pojawił się folder dist. Folder dist zawiera naszą zbandlowaną aplikację, to znaczy widzimy, że mamy tutaj plik index.html, w którym mamy script i w którym mamy pliki css. Jeśli sprawdzimy sobie ten folder assets to faktycznie mamy tutaj dwa pliki js, które zawierają m.in. cały kod źródło
wy Reacta, ale również zmimifikowaną logikę naszej aplikacji, a więc wszystkie komponenty, które tworzyliśmy, całą logikę, którą dodaliśmy no i mamy też plik ze stylami, czyli te nasze drobne style, które dodaliśmy w celu przećwiczenia stylowania aplikacji. Pozostaje nam wrzucić taki zestaw plików na hosting. Jeśli chodzi o hosting to ja standardowo początkującym polecam Netlify, bo jest naprawdę bardzo intuicyjny, prosty i przede wszystkim darmowy. A więc jeśli wejdziemy sobie na naszą stronę N
etlify, to w naszej zakładce sites możemy wybrać add new site i potem deploy manually. Widzimy, że mamy tutaj taki piękny element pokazujący, że możemy tutaj przeciągnąć output folder naszej strony, tak więc zlokalizujmy sobie nasz folder w plikach lokalnych, folder dist i po prostu przeciągnijmy go w to miejsce. Po opuszczeniu strona zostaje uploadowana i po chwili pojawia się już ona na liście naszych stron. Możemy kliknąć open production deploy i widzimy, że mamy już naszą stronę dostępną pod
konkretnym linkiem. Więc tak naprawdę bandlowanie takich statycznych aplikacji jest bardzo proste. Wpisujemy npm run build, a potem wynikowy folder dist wrzucamy na nasz hosting, niezależnie od tego jakiego hostingu korzystamy. A więc to tyle, nasza aplikacja jest już gotowa. Przejdźmy teraz do podsumowania i porozmawiajmy o tym, jakie następne kroki postawić w nauce Reacta. Podsumujmy czego nauczyliśmy się w tym filmie. Wiemy czym jest React, ReactDOM i JSX. Wiemy jak stawiać projekty za pomoc
ą VIT. Wiemy jak tworzyć komponenty i zapewniać im interaktywność. Wiemy jak obsługiwać formularze i renderować listy. Wiemy jak w podstawowy sposób stylować aplikację i deployować ją. Co dalej? Cóż, przede wszystkim zachęcam do praktyki. Spróbuj wykorzystać zdobytą wiedzę samodzielnie. Na start możesz jeszcze raz napisać tę listę kontaktów. Tym razem bez pomocy tutoriala. Możesz wzbogacić ją o dodatkowe featury takie jak usuwanie i edytowanie kontaktów. Dobrym pomysłem jest też stworzenie innyc
h aplikacji takich jak Todo albo kalkulator czy gra w memory. Jeśli czujesz się już pewnie z podstawami to czas przejść dalej. Kolejnym ważnym zagadnieniem jest komunikacja z backendem i reactowe hookie. Hookie to specjalne reactowe funkcje. Poznaliśmy już jedną z nich a mianowicie useState. Inne hookie są wykorzystywane m.in. do pobierania danych z backendu ale również do optymalizacji aplikacji. Dobrze byłoby też zapoznać się z jedną z trzech głównych metod stylowania. CSS modules, CSSJS albo
Tailwind CSS. Kiedy zaczniesz tworzyć kompleksowe aplikacje to prawdopodobnie przyjdzie czas na naukę mechanizmów takich jak Context i Reducer. A później fajnie byłoby wyjść poza bibliotekę reacta i poznać narzędzia takie jak Next.js Storybook czy React Hook Form. Gdzie się tego wszystkiego nauczyć? Oczywiście jeśli chodzi o zagadnienia reactowe to dokumentacja reacta jest świetnym źródłem informacji. Jeśli chodzi o dodatkowe narzędzia to wiele z nich również oferuje dobre tutoriale. Ja jednak c
hciałbym Cię już ostatni raz zachęcić do zerknięcia na zrozumiećreact.pl W naszym kursie przechodzimy zarówno przez wszystkie najważniejsze mechanizmy reacta ale przedstawiamy również popularne narzędzia takie jak Next.js. Dodatkowo po kilkudziesięciu godzin materiałów wideo dodajemy ponad 100 zadań i kompleksowy projekt praktyczny. Kurs jest aktualizowany. Jeśli do niego dołączysz to otrzymasz dostęp do wszystkich kolejnych edycji kursu. Pamiętaj o gwarancji satysfakcji. Masz aż 2 tygodnie na s
prawdzenie czy kurs Ci się podoba. Jeśli z jakiegoś powodu nie przypadnie Ci do gustu to oczywiście zwrócimy Ci wszystkie pieniążki. Na dzisiaj to już wszystko. Serdeczne dzięki za obejrzenie kursu do końca i do następnego razu. Cześć!

Comments

@JZP

Finalną cenę drugiej edycji kursu "Zrozumieć React" ogłosimy 8 kwietnia 2024. Aby dowiedzieć się o niej w pierwszej kolejności zapisz się na listę oczekujących na https://zrozumiecreact.pl/

@konradbauer8098

Jestem uczestnikiem kursu, szczerze polecam. Pomimo tege że ukończyłem wcześniej inny bardzo dobry kurs, to jestem bardzo zadowolony ponieważ w tym kursie dużo rzeczy jest tłumaczone w bardzo jasny sposób - co i jak działa "pod maską" Reacta. Najważniejsze - kurs jest jak najbardziej aktualny pod względem technologii. Ponadto Filip i Kacper deklarują że kurs będzie oczywiście aktualizowany na co szczerze liczę. Przykładem tego jest aktualizacja modułu o NEXT.js na najnowszą wersję 14 :)

@dariuszmion2764

Trochę tam się znam w te klocki i przez ten prymat mogę powiedzieć, że kurs tutaj udostępniony jest prowadzony profesjonalnie 🤠

@Dzinn40

Najlepszy kurs Reacta z jakim miałem do czynienia. Konkretny i co najważniejsze AKTUALNY. Polecam każdemu zainteresowanemu nauczeniem się Reacta. Dobrze wydane pieniądze.

@Szadolowski

Jak ja wam dziękuję, właśnie rozwijam się w kierunku Front-End i jest to dla mnie jak manna z nieba dziękuję

@AlexanderLebedev_sortafreel

Świetne wprowadzenie do kursu, mam nadzieję, że wkrótce zobaczę więcej!

@pawlakpawlak88

Super materiał!!! Pracuje z React od kilku miesięcy ale dużo się dowiedzialem. Zmienił się też mój punkt postrzegania niektórych metod. Świetna robota @JZP!!!

@RobieMVPAplikacjeKarolBocian

Niesamowite mięso!!!

@StacyAcker

tylko raz można odebrać?

@siureksmoka989

za ile bedzie ten kurs ?

@WoonszBoa

Jest może jakiś link do repo z finalnym kodem?

@matys655

jaka cena kursu ?

@brainerr5512

jaka cenka kursu?

@whoisyou6654

wątpię że warto się uczyć jeszcze bo zmienił się trend na rynku, firmy już nie oczekują najnowszych rozwiązań technologicznych czyli programista react piszący kod przez miesiąc tylko szybkich i sprawdzonych dodając do tego ai, raczej już nie warto się uczyć programowania