Download as pdf or txt
Download as pdf or txt
You are on page 1of 50

INŻYNIERIA INTERNETU

WYKŁADY INFORMATYKA TECHNICZNA


2023/2024

REACT

Krzysztof Bzowski <kbzowski@agh.edu.pl>


DOM
• DOM (Document Object Model)
to struktura drzewiasta, która
reprezentuje elementy strony
internetowej w przeglądarce
internetowej. Jest to
abstrakcyjny interfejs
programowania, który umożliwia
programistom manipulowanie
zawartością strony internetowej
i jej wyglądem za pomocą kodu
JavaScript.
SPA – SINGLE PAGE APPLICATION
• MPA (Multiple Page Application) to klasyczne rozwiązanie, w którym
dynamiczna treść HTML jest generowana po stronie serwerowej.
• SPA (Single Page Application) – aplikacja renderowana jest w
przeglądarce. Dzięki temu kolejne akcje nawigacji odbywają się bez
przeładowania całej strony, a jedynie części drzewa DOM. Nie oznacza
to, że aplikacja zbudowana jest z jednej strony, ale że jej zawartość
dynamicznie może się zmieniać. Technicznie, jest to jeden plik HTML
w którym umieszczamy i podmieniamy komponenty. Zwykle* cała
aplikacja jest ładowana na początku i tylko dynamicznie
aktualizowana, gdy użytkownik interaktywnie działa z aplikacją.

*Istnieją metody tzw. dynamicznego importu komponentów (tzw. Lazy Loading) pozwalający na Code Splitting.
Kod komponentów ładowany jest na życzenie
STRATEGIE RENDEROWANIA STRON WWW
1.Static Site Generation (SSG) – Gatsby, Astro
1. Strony są generowane w czasie budowy aplikacji i serwowane jako gotowe pliki
HTML.
2. Zawartość jest statyczna i taka sama dla wszystkich użytkowników.
3. Brak interakcji z serwerem (np. bazą danych), bardzo szybkie renderowanie
strony
4. Bardzo dobra optymalizacja dla silników wyszukiwania (SEO)
2.Client-Side Rendering (CSR) – React
1. Zawartość strony jest renderowana w przeglądarce użytkownika przy użyciu
JavaScript.
2. Strona, którą otrzymuje użytkownik, jest początkowo pusta lub zawiera tylko
minimalny szkielet, a cała zawartość ładuje się i renderuje po stronie klienta.
3. Prędkość renderowania zależy od klienta, słaba optymalizacja SEO – robot
indeksujący musi „uruchomić” JavaScript
3.Server-Side Rendering (SSR) – NextJS
1. Strony są renderowane na serwerze dla każdego żądania
2. Użytkownik otrzymuje kompletnie wyrenderowaną stronę, co jest korzystne
dla SEO i początkowej wydajności ładowania.
3. Możliwość buforowania stron - Incremental Static Regeneration (ISR)
WEBPACK – SERWER DEWELOPERSKI
• Serwer deweloperski (debugowanie i odświeżanie)
• Służy łączeniu kodu (ang. Bundle) i usuwaniu nieużywanego kodu
(ang. tree-shaking)
• Integruje narzędzia transpilujące kod (np. Babel)
• Konfigurowalny za pomocą webpack.config.js
REACT
React to biblioteka JavaScript do
tworzenia interfejsów
użytkownika, która została
stworzona przez Facebook (Meta).
Jest ona wykorzystywana do
budowania aplikacji, w których
potrzebna jest szeroka interakcja z
użytkownikiem.
REACT CECHY
• Komponentowy – React jest oparty na komponentach, co oznacza, że
aplikacja składa się z małych, izolowanych części, które można łatwo
testować i ponownie używać.
• Działa na wirtualnym drzewie DOM (vDOM) - aktualizując tylko te
fragmenty DOM które uległy zmianie. Aktualizacą DOM zajmuje się
algorytm Uzgodnienia (ang. Reconciliation) stanowiący sedno
działania React
REACT CECHY - KOD DEKLARATYWNY A IMPERATYWNY
• Paradygmat imperatywny - skupia się na opisie krok po kroku, jak coś ma być wykonane.

• Kod deklaratywny - mówimy komputerowi co ma dla nas zrobić, opisujemy wynik który chcemy
otrzymać. Pozwala skupić się na wyniku a nie na sposobie w jaki rozwiązujemy problem.
KOMPONENT
Komponent może być funkcją lub klasą. Reprezentuje pewien fragment
aplikacji

Komponent oparty o funkcję Komponent oparty o klasę (przestarzały)

Dalsza część wykładu będzie zakładała pracę


na komponentach funkcyjnych!
Obecnie niezalecane podejście!
JSX, to składnia rozszerzająca język JavaScript, która
KOMPONENT pozwala na pisanie elementów interfejsu
użytkownika w sposób podobny do HTML, ale
bezpośrednio w pliku JavaScript/TypeScript.
• Komponent musi zwracać JSX lub null JSX tworzy wizualną reprezentację komponentu.

To nie jest łańcuch znaków (string) ani HTML

Transpilator

Przeglądarka
KOMPONENT W TYPESCRIPT
Parametry komponentu mogą być
zarówno opisane typem jak i
interfejsem Komponent musi mieć nazwę pisaną wielką literą (to go odróżnia)

Komponent może przyjmować parametry


(ang. properties) w skrócie props.
Jest to zawsze jeden obiekt będący
parametrem funkcji

Zwrócenie wielu linijek JSX wymaga dodania nawiasów!

Jeśli w JSX chcemy osadzić (wyświetlić) dane


muszą być one w klamerkach!
KOMPONENT W TYPESCRIPT
Proces wyświetlenia komponentu na interfejsie
użytkownika (UI) nazywamy renderowaniem.

Nazwa funkcji – nazwa komponentu -> nazwa tagu JSX


Parametry funkcji – parametry komponentu -> atrybuty tagu
JSX
KOMPONENT W TYPESCRIPT
Komponenty można deklarować na wiele sposobów (wszystkie są
równorzędne!)

Destrukturyzacja bezpośrednio w miejscu deklaracji Komponent zadeklarowany jako funkcja strzałkowa


parametrów
KOMPONENT W TYPESCRIPT
Komponenty można deklarować na wiele sposobów (wszystkie są
równorzędne!)

Destrukturyzacja bezpośrednio w miejscu deklaracji parametrów w funkcji


strzałkowej z jawnym zadeklarowaniem typu zwracanego (FC – Functional
Component)
CYKL ŻYCIA KOMPONENTU
• Montowanie („Narodziny” komponentu)
komponent jest tworzony i po raz pierwszy wstawiany do drzewa
DOM
• Aktualizacja („Życie” komponentu)
Komponent może być wielokrotnie aktualizowany poprzez zmianę
parametrów i/lub swojego stanu
• Odłączanie („Śmierć” komponentu)
Gdy komponentu już nie potrzebujemy (na przykład zmieniamy stronę
lub usuwamy część interfejsu), komponent jest odłączany od drzewa
DOM. Stan komponentu jest tracony!
HOOK
• Hook to funkcja specjalna w bibliotece React, która
umożliwia korzystanie z funkcjonalności React w
komponentach funkcyjnych. Hooki zostały
wprowadzone w React 16.8 jako uzupełnienie do
klasowych komponentów.
• Pozwalają one na reużywalność i enkpasulację logiki
między różnymi komponentami. Dzięki temu, że
hooki pozwalają na rozdzielenie logiki od widoku,
możemy łatwo przepisywać i przenosić kod między
różnymi komponentami, co oszczędza czas i
zmniejsza ryzyko błędów.
HOOK
• Hooki w React
• Nazwy hooków muszą zaczynać się od prefiksu "use". Jest to konwencja,
która pozwala na łatwe rozpoznawanie hooków i odróżnianie ich od innych
funkcji.
• Hooki muszą być wywoływane w tych samych miejscach przy każdym
renderowaniu. Nie można ich wywoływać wewnątrz instrukcji warunkowej
lub pętli, ponieważ to może prowadzić do niestabilnego zachowania
komponentu.
• Nie można używać hooków poza komponentami funkcyjnymi lub innymi
hookami.
STAN KOMPONENTU
• Stan komponentu to zbiór danych, które są przechowywane w komponencie i mogą ulegać
zmianom w czasie życia komponentu.
• Komponent jest aktualizowany (renderowany) w DOM TYLKO jeśli jego stan lub parametry ulegną
zmienia.
Zadeklaruj zmienną stanu na początku
komponentu
useState przyjmuje wartość inicjalizująca stan.
Trzeba go sparametryzować, jeśli typ stanu nie
może być wywnioskowany z inicjalizatora!

useState zwraca tablicę: [wartość, setter]


którą destrukturyzujemy (konwencja).
Zawsze przypisuj stan do stałych (const)!

Chcą zmienić stan zawsze użyj setera.


Modyfikacja bezpośrednio stanu nie
aktualizuje komponentu
STAN KOMPONENTU

Aktualizacja wartości zwyczajnej zmiennej nie Aktualizacja wartości stanu bezpośrednio nie
spowoduje aktualizacji komponentu spowoduje aktualizacji komponentu (należy użyć
setera!)

Brak aktualizacji komponentu == brak aktualizacji UI


STAN KOMPONENTU

Stan można sparametryzować typem


jawnym

Jeśli logika zdarzenia jest zbyt


skomplikowana należy ją oddelegować
do dedykowanej funkcji!
W takim przypadku podajemy tylko
nazwę (referencję) do obsługującej
zdarzenie funkcji
TABLICA W STANIE

Zmiana stanu nastąpi kiedy zmianie ulegnie wartość


prymitywu lub adres w pamięci

Atrybut key jest wymagany w dynamicznie tworzonych komponentach Alternatywny zapis


(tj. takich które nie są znane na etapie kompilacji). Musi być UNIKALNY w komponencie!
OBIEKT W STANIE
WIELOKROTNA ZMIANA STANU
Wielokrotna zmiana stanu spowoduje tylko W takich przypadkach stosujemy seter funkcyjny
pojedynczą zmianę. Dlaczego? z odniesieniem do poprzedniej wartości

Użycie takiej konstrukcji zagwarantuje, że każde wywołanie funkcji


aktualizującej otrzyma najbardziej aktualną wartość stanu.
USEREDUCER
Alternatywny sposób zarządzania złożonym stanem, w którym podlega on różnym zmianom (a nie
tylko podmianie)
STAN KOMPONENTU - WSPÓŁDZIELENIE
EFEKT UBOCZNY (ANG. SIDE EFFECT)

Funkcja czysta (ang. pure function) Funkcja z efektami ubocznymi (ang. impure function)

Czysta funkcja to funkcja, która zawsze zwraca to


samo wyjście po podaniu określonego wejścia.
Innymi słowy: działanie jest przewidywalne
Zalety: Testowalność, przewidywalność, łatwość Oprócz zwracania wartości, funkcja wpływa na stan
zrozumienia zewnętrzny lub zależy od jakiegoś stanu zewnętrznego, co
może prowadzić do różnych wyników przy każdym
wywołaniu tej samej funkcji z tymi samymi argumentami.

Efekt uboczny w programowaniu odnosi się do sytuacji, w której funkcja lub wyrażenie modyfikuje stan
zewnętrzny lub ma obserwowalną interakcję z zewnętrznymi stanami poza swoim własnym zakresem. Innymi
słowy, efekt uboczny występuje, gdy operacja powoduje zmiany poza swoim lokalnym środowiskiem, które
mogą wpłynąć na wykonanie innych części programu.
USEEFFECT – OBSŁUGA EFEKTÓW UBOCZNYCH W REACT
• Logika renderująca nie może zawierać efektów ubocznych
• Czym są efekty uboczne? Wszystko co dzieje się „poza” komponentem
• Zdarzenia przeglądarki (np. zmiana wielkości okna)
• Timery (setInterval, setTimeout)
• Czynności które wymagają czyszczenia (np. subskrypcje danych z sieci)
• Coś ma być uruchomione tylko raz przy montowaniu komponentu (np. zapytanie API)
• Reagowanie na zmianę parametrów lub stanu
• Kod umieszczony w useEffect zadziała po każdym renderowaniu lub gdy
zmianie ulegną wartości zadane w zależnościach (dependancies) – drugim
parametrze - useEffect(fun, [deps])
• UseEffect może zwrócić funkcję uruchamianą podczas usuwania
komponentu z DOM (odmontowywania, ang. unmounting)
USEEFFECT useEffect(fun, [deps])

Brak drugiego argumentu


Pusta tablica w drugim parametrze (deps) –
(efekt uruchamiany przy KAŻDYM renderowaniu).
uruchom raz przy pierwszym renderowaniu
Łatwo doprowadzić do nieskończonej pętli!
USEEFFECT

Efekt zostanie uruchomiony zostanie za każdym razem gdy stan count się zmieni,
ponieważ w drugim argumencie mamy count
USEEFFECT – ZMIANA PROPS
Początkowy stan komponentu jest ustawiany
na podstawie propsa initial

Kliknięcie „Naciśnij mnie” nie spowoduje


zmiany stanu w komponencie Counter,
Ponieważ jest on już zainicjalizowany
(inicjalizacja stanu następuje tylko raz)
Wykorzystujemy useEffect do „monitorowania”
parametru initial komponentu.
W przypadku jego zmiany, ustawiamy nowy
stan
USEEFFECT - PORZĄDKI
useEffect NIE musi nic
zwracać. Ale jeśli zostanie
zwrócona funkcja – to
wykona się w momencie
USUNIĘCIA komponentu z
drzewa (ang. umount).

Wykonaj RAZ przy zamontowaniu


(ang. Mount) komponentu

Co się stanie jeśli nie zastopujemy timera?


USEMEMO val = useMemo(fun, [deps])

• Zwraca zapamiętaną wartość wyrażenia. Pozwala na „cachowanie”


obliczonych wartości, które byłyby kosztowne w liczeniu za każdym
razem gdy komponent ulega wyrenderowaniu

„Kosztowna obliczeniowo funkcja”

Używać rozważnie,
„cachowanie” nie jest
za darmo

Wartość zwracana będzie


umieszczona w cache, dopóki
wartość parametru w [] się nie
zmieni
USECALLBACK
Pozwala zapamiętać zwróconą przez funkcję wartość (memoizacja).
Gwarantuje stabilność wyniku dopóki nie zmieni wartość parametru
sterującego.
REACT - KOMPONENTY
• W komponencie możemy używać dowolnych tagów HTML oraz innych
komponentów React – ale możemy zwrócić tylko jeden element
nadrzędny (rodzic). Można użyć pseudo rodzica
<Ract.Fragment/> lub <></> do opakowania kodu jeśli istnieje
konieczność zwrócenia więcej (i nie chcemy wprost stosować innego
tagu)
REACT - RENDEROWANIE
• React zaplanuje renderowanie za każdym razem, gdy zmieni się stan
komponentu lub wartości parametrów (props)
• Kiedy komponent rodzic zostanie ponownie wyrenderowany
wszystkie dzieci również zostaną „odświeżone”
REACT - KOMPONENTY
• Konwencja: Nazwa pliku – nazwa komponentu
• Klamerek używamy do osadzania danych w atrybutach
(paramtetrach) - stringów nie trzeba dawać w klamerkach
• Pewne atrybuty HTML są niedozwolone i mają swoje
zastępstwa (np.class => className), key (zarezerwowany)
• Komponent React zawsze powinien mieć nazwę z wielkiej
litery (małe litery przeznaczone dla natywnego HTML)
• Parametry komponentu zawsze powinny być cameCase
• Parametry zawsze są read-only – nie wolno ich
modyfikować
• Dowolne dane mogą być parametrem
RENDEROWANIE WARUNKOWE
2
1

3
ERRORBOUNDARIES (GRANICE BŁĘDÓW)
• Przechwytywanie i obsługę błędów w komponentach
ERRORBOUNDARIES (GRANICE BŁĘDÓW)
• Biała strona śmierci
(ang. white screen of death)
• F12 lub narzędzia programistów
• Zakładka: Konsola
ERRORBOUNDARIES - ROZWIĄZANIE

yarn add react-error-boundary

Granice błędów zatrzymują propagację błędów w drzewie komponentów


i pozwalają na ich obsługę.
DEBUGOWANIE
• Webstorm:
• Run -> Edit Configuration
• Dodaj: JavaScript Debug
• Podaj nazwe (Debug)
• URL (jak w przeglądarce:
localhost:3000)
• Reconnect automatically
ROUTING/NAWIGACJA
• React nie posiada wbudowanych mechanizmów routingu między
„podstronami”.
• Najpopularniejszym rozwiązaniem jest biblioteka:
react-router-dom
ROUTING/NAWIGACJA
FETCH VS XMLHTTPREQUEST
XMLHttpRequest fetch
const xhr = new XMLHttpRequest(); try {
const response = await fetch("http://localhost:9000/api/books",
xhr.open('GET', 'http://localhost:9000/api/books'); { method: "GET" }
);
xhr.onreadystatechange = () => { const data = await response.json();
if (xhr.readyState !== 4) return; // obsluga danych
if (xhr.status === 200) { } catch (e) {
const data = JSON.parse(xhr.responseText); // obsluga wyjatku komunikacyjnego!
// obsluga danych }
} else {
console.log('HTTP error', xhr.status, xhr.statusText);
}
};

xhr.onerror = () => {
// obsluga wyjatku komunikacyjnego!
};

xhr.send();
FETCH VS XMLHTTPREQUEST
• Przeglądarka implementuje dwa API komunikacyjne
• XMLHttpRequest
• API opracowane w 1999 na potrzeby AJAX (Asynchronous JavaScript and XML)
• Strumienie są cachowane w pamięci
• Wparcie dla postępu pobierania danych
• Wparcie dla Timeout
• Wparcie dla przerwania połączenia
• Fetch
• Natywne API opracowane w 2015
• Wspiera Cache (no-store, force-cache itp.)
• Wpiera no-cors (w ograniczonym stopniu)
• Wpiera streaming danych (możliwość pobrania danych w częściach, przykład dużego pliku csv)
• Dostępny w node (od wersji 18)
• Wyjątek powoduje tylko błąd sieci
• Brak wsparcia dla postępu pobierania danych ani timeout
• Przerwanie połączenia możliwe przy użyciu AbortController

Jeśli nie musisz wspierać BARDZO STARYCH przeglądarek powinieneś użyć fetch
ROZWIĄZANIA OPARTE BIBLIOTEKI STRON TRZECICH
• Implementacje oparte o XMLHttpRequest
• Axios (https://github.com/axios/axios)
• Implementacje oparte o fetch
• Ky (https://github.com/sindresorhus/ky) – tylko przeglądarka
• Gaxios (https://github.com/googleapis/gaxios)
• Got (https://www.npmjs.com/package/got) – tylko Node
• Undici (https://undici.nodejs.org/#/) – tylko Node

class HTTPError extends Error {}

const response = await fetch('https://example.com', {


method: 'POST',
body: JSON.stringify({ foo: true }),
headers: { import ky from 'ky';
'content-type': 'application/json',
}, const json = await ky.post('url', {json: {foo: true}}).json();
});

if (!response.ok) {
throw new HTTPError(`Fetch error: ${response.statusText}`);
}

const json = await response.json();


KOMUNIKACJA Z API
KOMUNIKACJA Z
API

You might also like