Opisywanie UI
React jest biblioteką javascriptową służącą do renderowania interfejsu użytkownika (UI). UI jest zbudowany z małych części, np. przyciski, tekst czy obrazki. React pozwala zgrupować je w komponenty, które można zagnieżdżać i używać ich wielokrotnie. Zarówno na stronach internetowych, jak i w aplikacjach mobilnych, wszystko, co znajduje się na ekranie, można rozbić na osobne komponenty. W tym rozdziale nauczysz się tworzyć, modyfikować i wyświetlać warunkowo komponenty reactowe.
W tym rozdziale
- Jak napisać swój pierwszy komponent
- Kiedy i jak tworzyć wielokomponentowe pliki
- Jak dodać znaczniki do JavaScriptu za pomocą JSX
- Jak używać nawiasów klamrowych w JSX w celu dostania się do funkcjonalności javascriptowej z poziomu komponentu
- Jak skonfigurować komponenty za pomocą właściwości
- Jak wyrenderować komponenty warunkowo
- Jak wyrenderować wiele komponentów jednocześnie
- Jak unikać trudnych w zwalczaniu błędów poprzez tworzenie czystych komponentów
- Dlaczego warto patrzeć na UI jak na drzewo
Twój pierwszy komponent
Aplikacje reactowe buduje się z odizolowanych od siebie kawałków UI zwanych komponentami. Komponent reactowy jest funkcją javascriptową, którą można “okrasić” znacznikami. Komponentem może być pojedynczy przycisk, ale także cała strona. Oto przykład komponentu o nazwie Gallery
, renderującego komponenty Profile
:
function Profile() { return ( <img src="https://i.imgur.com/MK3eW3As.jpg" alt="Katherine Johnson" /> ); } export default function Gallery() { return ( <section> <h1>Niesamowici naukowcy</h1> <Profile /> <Profile /> <Profile /> </section> ); }
Chcesz zgłębić ten temat?
Aby dowiedzieć się, jak deklarować i używać komponentów reactowych, przeczytaj rozdział pt. Twój pierwszy komponent.
Czytaj dalejImportowanie i eksportowanie komponentów
W jednym pliku możesz zadeklarować wiele komponentów naraz, lecz duże pliki są trudne w czytaniu i utrzymaniu. Aby poradzić sobie z tym problemem, możesz wyeksportować komponent z jednego pliku, a następnie zaimportować go w innym:
import Profile from './Profile.js'; export default function Gallery() { return ( <section> <h1>Niesamowici naukowcy</h1> <Profile /> <Profile /> <Profile /> </section> ); }
Chcesz zgłębić ten temat?
Aby dowiedzieć się więcej o wydzielaniu komponentów do osobnych plików, przeczytaj rozdział pt. Importowanie i eksportowanie komponentów.
Czytaj dalejDodawanie znaczników w JSX
Każdy komponent reactowy jest funkcją javascriptową, która może zawierać w sobie kod znaczników renderowany do przeglądarki. Komponenty reactowe używają rozszerzenia składni zwanego JSX w celu przedstawienia tego kodu znaczników. JSX wygląda bardzo podobnie do HTML-a, jednak jest nieco bardziej restrykcyjny i potrafi wyświetlać dynamiczne dane.
Jeśli tak po prostu wkleimy istniejący kod HTML do komponentu reactowego, nie zawsze będzie on działał:
export default function TodoList() { return ( // Nie do końca to zadziała! <h1>Lista zadań Hedy Lamarr</h1> <img src="https://i.imgur.com/yXOvdOSs.jpg" alt="Hedy Lamarr" class="photo" > <ul> <li>Wynaleźć nową sygnalizację świetlną <li>Przećwiczyć scenę do filmu <li>Usprawnić technologię rozpraszania widma </ul>
Jeśli posiadasz już kod HTML, możesz go przekształcić automatycznie za pomocą konwertera:
export default function TodoList() { return ( <> <h1>Lista zadań Hedy Lamarr</h1> <img src="https://i.imgur.com/yXOvdOSs.jpg" alt="Hedy Lamarr" className="photo" /> <ul> <li>Wynaleźć nową sygnalizację świetlną</li> <li>Przećwiczyć scenę do filmu</li> <li>Usprawnić technologię rozpraszania widma</li> </ul> </> ); }
Chcesz zgłębić ten temat?
Aby dowiedzieć się jak poprawnie pisać kod JSX-owy, przeczytaj rozdział pt. Pisanie kodu w JSX.
Czytaj dalejJavaScript w JSX a nawiasy klamrowe
JSX pozwala na pisanie kodu podobnego do HTML-a wewnątrz pliku javascriptowego, umożliwiając trzymanie logiki renderowania i treści jednym miejscu. Czasem jednak zachodzi potrzeba, by w kodzie znaczników dodać nieco logiki javascriptowej lub odnieść się do dynamicznej własności. W takiej sytuacji możemy użyć nawiasów klamrowych, otwierając tym samym okno do świata JavaScriptu:
const person = { name: 'Gregorio Y. Zara', theme: { backgroundColor: 'black', color: 'pink' } }; export default function TodoList() { return ( <div style={person.theme}> <h1>{person.name} - lista zadań</h1> <img className="avatar" src="https://i.imgur.com/7vQD0fPs.jpg" alt="Gregorio Y. Zara" /> <ul> <li>Usprawnić wideotelefon</li> <li>Przygotować wykłady o aeronautyce</li> <li>Opracować silnik napędzany alkoholem</li> </ul> </div> ); }
Chcesz zgłębić ten temat?
Aby dowiedzieć się więcej na temat dostępu do danych javascriptowych z poziomu kodu JSX, przeczytaj rozdział pt. JavaScript w JSX a nawiasy klamrowe.
Czytaj dalejPrzekazywanie wartości do komponentu
Komponenty reactowe komunikują się ze sobą za pomocą właściwości (ang. props). Każdy komponent-rodzic może przekazać informacje do swoich potomków właśnie poprzez właściwości. Właściwości mogą kojarzyć ci się z atrybutami HTML-owymi, jednak przez właściwości możesz przekazać dowolną wartość javascriptową, nawet obiekty, tablice, funkcje czy sam kod JSX!
import { getImageUrl } from './utils.js' export default function Profile() { return ( <Card> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> </Card> ); } function Avatar({ person, size }) { return ( <img className="avatar" src={getImageUrl(person)} alt={person.name} width={size} height={size} /> ); } function Card({ children }) { return ( <div className="card"> {children} </div> ); }
Chcesz zgłębić ten temat?
Aby dowiedzieć się, jak przekazywać i odczytywać właściwości, przeczytaj rozdział pt. Przekazywanie wartości do komponentu.
Czytaj dalejRenderowanie warunkowe
Twoje komponenty często będą musiały wyświetlać różne rzeczy w zależności od okoliczności. W Reakcie możesz wyrenderować kod JSX-owy warunkowo używając składni javascriptowej: instrukcji if
oraz operatorów &&
i ? :
.
W tym przykładzie użyliśmy operatora &&
do warunkowego wyrenderowania tzw. “ptaszka”:
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✔'} </li> ); } export default function PackingList() { return ( <section> <h1>Lista rzeczy do spakowania Sally Ride</h1> <ul> <Item isPacked={true} name="Skafander kosmiczny" /> <Item isPacked={true} name="Hełm ze złotym liściem" /> <Item isPacked={false} name="Zdjęcie Tam" /> </ul> </section> ); }
Chcesz zgłębić ten temat?
Aby poznać różne sposoby renderowania warunkowego, przeczytaj rozdział pt. Renderowanie warunkowe.
Czytaj dalejRenderowanie list
Na pewno często zdarzy ci się wyświetlić kilka podobnych komponentów na podstawie jakiejś kolekcji danych. W Reakcie możesz użyć javascriptowych funkcji filter()
i map()
, aby przekształcić tablicę danych w tablicę komponentów.
Dla każdego elementu tablicy musisz określić key
(pol. klucz). Zwykle używa się w tym celu ID pobranego z bazy. Klucze umożliwiają Reactowi śledzenie pozycji każdego z elementów listy w sytuacji, gdy ulega ona zmianie.
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const listItems = people.map(person => <li key={person.id}> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} znany(-a) za {person.accomplishment} </p> </li> ); return ( <article> <h1>Naukowcy</h1> <ul>{listItems}</ul> </article> ); }
Chcesz zgłębić ten temat?
Aby dowiedzieć się jak wyrenderować listę komponentów i jak wybrać odpowiednie klucze, przeczytaj rozdział pt. Renderowanie list.
Czytaj dalejCzyste komponenty
W JavaScripcie niektóre funkcje są czyste. Czysta funkcja:
- Zajmuje się tylko swoimi sprawami. Nie zmienia żadnych obiektów ani zmiennych, które istniały przed jej wywołaniem.
- To samo wejście, to samo wyjście. Dla takich samych danych wejściowych czysta funkcja zawsze zwraca ten sam wynik.
Pisząc komponenty w formie czystych funkcji możesz ustrzec się przed masą kłopotliwych błędów i nieprzewidywalnych zachowań w razie rozrostu projektu. Poniżej przedstawiliśmy przykład komponentu nieczystego:
let guest = 0; function Cup() { // Źle: zmienia istniejącą wcześniej zmienną! guest = guest + 1; return <h2>Herbatka dla gościa #{guest}</h2>; } export default function TeaSet() { return ( <> <Cup /> <Cup /> <Cup /> </> ); }
Możesz przekształcić ten komponent w czysty przekazując mu właściwość zamiast modyfikować istniejącą już zmienną:
function Cup({ guest }) { return <h2>Herbatka dla gościa #{guest}</h2>; } export default function TeaSet() { return ( <> <Cup guest={1} /> <Cup guest={2} /> <Cup guest={3} /> </> ); }
Chcesz zgłębić ten temat?
Aby dowiedzieć się jak pisać czyste funkcje o łatwym do przewidzenia wyniku działania, przeczytaj rozdział pt. Czyste komponenty.
Czytaj dalejTwój UI jako drzewo
React używa drzew do modelowania relacji pomiędzy komponentami i modułami.
Drzewo renderowania w Reakcie to reprezentacja relacji rodzic-dziecko między komponentami.
Komponenty blisko góry drzewa, w okolicach głównego komponentu (ang. root component), uważane są za komponenty najwyższego poziomu (ang. top-level components). Komponenty, które nie posiadają komponentów potomnych, są liśćmi (ang. leaf components). Takie kategoryzowanie komponentów jest przydatne do zrozumienia przepływu danych i wydajności renderowania.
Modelowanie relacji między modułami javascriptowymi to kolejny przydatny sposób na zrozumienia jak działa aplikacja. Nazywamy to drzewem zależności modułów.
Drzewo zależności jest często wykorzystywane przez narzędzia do budowania w celu bundlowania całego kodu JavaScript, niezbędnego dla klienta do pobrania i renderowania. Duży rozmiar bundla wpływa negatywnie na doświadczenie użytkownika w aplikacjach reactowych. Zrozumienie drzewa zależności modułów jest pomocne przy debugowania tego typu problemów.
Chcesz zgłębić ten temat?
Przeczytaj rozdział Twój UI jako drzewo, aby dowiedzieć się, jak tworzyć drzewa renderowania i zależności modułów dla aplikacji reactowych oraz jak mogą być one przydatne jako modele mentalne używane do poprawy doświadczenia użytkownika i wydajności aplikacji.
Czytaj dalejCo dalej?
Zacznij od rozdziału pt. Twój pierwszy komponent!
Albo, jeśli znasz już ten temat od podszewki, może chcesz dowiedzieć się, jak dodać interaktywność w aplikacji?