Witaj w świecie Reacta! 🚀 Jeśli chcesz tworzyć dynamiczne i interaktywne interfejsy użytkownika, to właśnie znalazłeś/aś odpowiednie narzędzie. React to potężna biblioteka JavaScript, która zmienia podejście do budowania aplikacji webowych, koncentrując się na komponentach – niezależnych, wielokrotnego użytku elementach Twojego interfejsu. Gotowy/a, by zanurzyć się w świat deklaratywnego UI i wirtualnego DOM? Zaczynajmy! ✨
>>Spis treści
- Czym jest React?
- Dlaczego React? Główne zalety
- Podstawowe pojęcia w React
- Tworzenie pierwszej aplikacji React z Vite
- Komponenty funkcyjne i Hooki (Hooks)
- Podsumowanie
- Zadania do wykonania
>>Czym jest React?
React (często nazywany też React.js lub ReactJS) to popularna, otwarta biblioteka JavaScript do budowania interfejsów użytkownika (UI), stworzona i utrzymywana przez Meta (dawniej Facebook). ⚛️ Nie jest to pełnoprawny framework, jak np. Angular, ale skupia się wyłącznie na warstwie widoku w aplikacjach webowych i mobilnych (React Native).
Jego główną filozofią jest tworzenie interfejsów z małych, niezależnych i wielokrotnego użytku części, zwanych komponentami. Dzięki temu, budowanie złożonych aplikacji staje się bardziej uporządkowane, modułowe i łatwiejsze w zarządzaniu. React stał się standardem w branży front-endu, wykorzystywanym przez tysiące firm na całym świecie, od małych startupów po gigantów technologicznych.
>>Dlaczego React? Główne zalety
React zyskał ogromną popularność dzięki wielu korzyściom, które oferuje deweloperom:
- Komponentowa architektura: Wszystko w React to komponent! 🧱 Dzięki temu możesz dzielić interfejs na małe, izolowane kawałki, które łatwo testować, rozwijać i ponownie wykorzystywać w różnych częściach aplikacji. To promuje podejście "buduj raz, używaj wszędzie".
- Deklaratywne podejście: W React opisujesz, jak powinien wyglądać interfejs w danym stanie, a React zajmuje się resztą. Nie musisz martwić się o kroki manipulacji DOM (Document Object Model) – React zrobi to za Ciebie. To sprawia, że kod jest bardziej przewidywalny i łatwiejszy do debugowania.
- Wydajność dzięki Wirtualnemu DOM: React używa Wirtualnego DOM, czyli lekkiej kopii prawdziwego DOM w pamięci. Kiedy stan aplikacji się zmienia, React najpierw aktualizuje Wirtualny DOM, porównuje go z poprzednim stanem i dopiero wtedy efektywnie aktualizuje tylko te fragmenty prawdziwego DOM, które faktycznie się zmieniły. To minimalizuje kosztowne operacje na DOM i sprawia, że aplikacje są szybkie. ⚡️
- Jednokierunkowy przepływ danych: Dane w React płyną z góry na dół (od komponentów nadrzędnych do podrzędnych) poprzez tzw. propsy. To upraszcza debugowanie i zarządzanie stanem aplikacji, czyniąc ją bardziej przewidywalną.
- Duża społeczność i ekosystem: React ma ogromną i aktywną społeczność deweloperów. Znajdziesz mnóstwo tutoriali, narzędzi, bibliotek pomocniczych (np. do routingu, zarządzania stanem) i wsparcia. To oznacza, że prawdopodobnie znajdziesz rozwiązanie na każdy problem, jaki napotkasz. 🤝
- JSX: Specjalna składnia, która pozwala pisać kod przypominający HTML bezpośrednio w plikach JavaScript. Chociaż na początku może wydawać się dziwna, bardzo ułatwia wizualizację, jak dany komponent będzie wyglądał w przeglądarce.
>>Podstawowe pojęcia w React
Zanim zaczniemy pisać kod, poznajmy kluczowe terminy i koncepcje, które stanowią fundament Reacta.
>>>Komponenty: Serce Reacta
Jak już wspomnieliśmy, komponenty są podstawowymi budulcami każdej aplikacji React. Myśl o nich jak o niezależnych, wielokrotnego użytku elementach interfejsu, które mają swoją własną logikę i wygląd. Mogą to być proste elementy, takie jak przycisk czy pole tekstowe, albo bardziej złożone, jak pasek nawigacyjny czy cały formularz logowania.
W tym wprowadzeniu skupimy się na komponentach funkcyjnych, ponieważ są one obecnie standardem i wykorzystują Hooki, o których dowiemy się więcej za chwilę.
// Przykład prostego komponentu funkcyjnego
function Welcome() {
// Komponent funkcyjny, który zwraca JSX
return <h1>Welcome to React! 👋</h1>;
}
Ten komponent Welcome
renderuje prosty nagłówek <h1>
.
>>>JSX: JavaScript + XML/HTML
JSX (JavaScript XML) to rozszerzenie składni JavaScriptu, które pozwala nam pisać kod przypominający HTML bezpośrednio w plikach JavaScript. To może być mylące na początku, ponieważ miesza logikę JavaScript z deklaracjami UI, ale ma to na celu ułatwienie tworzenia komponentów.
const element = <h1>Hello, world!</h1>; // To jest JSX
Ważne: Przeglądarki nie rozumieją JSX. Jest on transpilowany (przetłumaczony) na standardowy JavaScript przez narzędzia takie jak Babel, zanim kod zostanie uruchomiony w przeglądarce. JSX jest konwertowany na wywołania funkcji createElement
(z pakietu react
).
// Ten JSX:
const element = <h1>Hello, world!</h1>;
// jest transpilowany do (uproszczone):
const element = React.createElement("h1", null, "Hello, world!");
Dzięki JSX kod jest bardziej intuicyjny i przypomina strukturę, którą widzimy w przeglądarce. ✨
>>>Propsy (Properties): Przekazywanie danych
Propsy (skrót od "properties") to sposób na przekazywanie danych z komponentu nadrzędnego (rodzica) do komponentu podrzędnego (dziecka). Działają one podobnie do atrybutów HTML i są tylko do odczytu – komponent podrzędny nie powinien modyfikować swoich propsów. To zapewnia jednokierunkowy przepływ danych, co ułatwia zarządzanie stanem aplikacji.
function Welcome(props) {
// Komponent funkcyjny przyjmuje obiekt props jako argument
return <h1>Hello, {props.name}! 👋</h1>;
}
function App() {
return (
<div>
<Welcome name="Alice" /> {/* Przekazujemy props 'name' */}
<Welcome name="Bob" /> {/* Kolejne użycie z innym propsem */}
</div>
);
}
// Renderowanie komponentu App spowoduje wyświetlenie:
// <h1>Hello, Alice!</h1>
// <h1>Hello, Bob!</h1>
>>>Stan (State): Zarządzanie danymi wewnętrznymi
Podczas gdy propsy służą do przekazywania danych z zewnątrz, stan (state) służy do zarządzania danymi, które są wewnętrzne dla komponentu i mogą się zmieniać w czasie. Kiedy stan komponentu się zmienia, React automatycznie ponownie renderuje ten komponent, aby odzwierciedlić nowe dane.
W komponentach funkcyjnych stan zarządzany jest za pomocą Hooków, w szczególności useState
.
import { useState } from "react"; // Importujemy Hook useState
function Counter() {
// Deklaracja stanu 'count' z początkową wartością 0
// 'count' to bieżąca wartość, 'setCount' to funkcja do jej aktualizacji
const [count, setCount] = useState(0);
const increment = () => {
setCount((prev) => prev + 1);
};
const decrement = () => {
setCount((prev) => prev - 1);
};
return (
<div>
<p>Count: {count}</p>
{/* Zwiększamy licznik */}
<button onClick={increment}>Increment</button>
{/* Zmniejszamy licznik */}
<button onClick={decrement}>Decrement</button>
</div>
);
}
Kliknięcie przycisków spowoduje zmianę stanu count
, co automatycznie zaktualizuje wyświetlaną wartość. 🔢
>>>Wirtualny DOM: Wydajne aktualizacje
Wirtualny DOM jest jednym z kluczowych powodów, dla których React jest tak wydajny. Zamiast bezpośrednio manipulować prawdziwym DOM (co jest kosztowne), React tworzy jego lekką kopię w pamięci.
Jak to działa?
- Kiedy stan aplikacji się zmienia, React tworzy nowy Wirtualny DOM.
- Porównuje go z poprzednim Wirtualnym DOM (proces zwany "diffing").
- Oblicza minimalną liczbę zmian potrzebnych do zaktualizowania prawdziwego DOM.
- Wprowadza te minimalne zmiany do prawdziwego DOM.
Dzięki temu React unika zbędnych operacji, co przekłada się na płynniejsze i szybsze działanie aplikacji, nawet przy częstych aktualizacjach. 🚀
>>Tworzenie pierwszej aplikacji React z Vite
Nowoczesne aplikacje React rzadko są tworzone od podstaw bez żadnego narzędzia. Zamiast przestarzałego create-react-app
, obecnie popularne są szybsze i bardziej elastyczne narzędzia takie jak Vite.
>>>Dlaczego Vite?
Vite to narzędzie do budowania front-endów, które oferuje bardzo szybkie uruchamianie serwera deweloperskiego (Dev Server) oraz błyskawiczne aktualizacje modułów (HMR - Hot Module Replacement). Dzieje się tak dzięki wykorzystaniu natywnych modułów ES w przeglądarce podczas dewelopmentu, co eliminuje potrzebę pełnej rekompilacji kodu przy każdej zmianie. Dla dewelopera oznacza to znacznie szybsze i przyjemniejsze doświadczenie. ⚡
>>>Inicjalizacja projektu
Kroki do utworzenia nowej aplikacji React z Vite:
- Upewnij się, że masz zainstalowany Node.js (wraz z npm lub yarn) na swoim komputerze.
- Otwórz terminal (lub wiersz poleceń).
- Uruchom polecenie:
lubnpm create vite@latest
yarn create vite
- Zostaniesz poproszony/a o podanie nazwy projektu (np.
my-react-app
). - Następnie wybierz framework:
React
. - Wybierz wariant:
JavaScript
(lubTypeScript
, jeśli znasz). - Po zakończeniu instalacji, przejdź do katalogu projektu:
cd my-react-app
- Zainstaluj zależności:
lubnpm install
yarn install
- Uruchom aplikację:
lubnpm run dev
To uruchomi serwer deweloperski, a Twoja aplikacja będzie dostępna pod adresemyarn dev
http://localhost:5173
(lub podobnym). 🎉
>>>Struktura projektu
Po utworzeniu aplikacji Vite zobaczysz następującą strukturę katalogów (uproszczoną):
my-react-app/
├── node_modules/ # Zależności projektu
├── public/ # Publiczne zasoby (np. favicon.svg)
├── src/ # Tutaj piszesz swój kod React!
│ ├── assets/ # Statyczne zasoby (np. logo.svg)
│ ├── App.css
│ ├── App.jsx # Główny komponent Twojej aplikacji (lub App.js jeśli wybrałeś JS)
│ ├── index.css
│ └── main.jsx # Główny plik JavaScript, który renderuje aplikację (lub main.js)
├── .gitignore
├── index.html # Główny plik HTML, do którego React będzie renderować aplikację
├── package.json # Informacje o projekcie i zależnościach
├── vite.config.js # Konfiguracja Vite
└── README.md
Najważniejsze pliki na początek to index.html
(główny plik, w którym React się "zakotwiczy"), src/main.jsx
(punkt wejścia aplikacji, gdzie React jest renderowany do DOM) i src/App.jsx
(główny komponent Twojej aplikacji).
>>Komponenty funkcyjne i Hooki (Hooks)
Współczesny React opiera się głównie na komponentach funkcyjnych i Hookach. Hooki to specjalne funkcje, które pozwalają komponentom funkcyjnym "zahaczać się" w stan Reacta i cykl życia (life-cycle) bez pisania klas. Są one kluczowe dla zarządzania stanem i efektami pobocznymi.
>>>useState
useState
to najczęściej używany Hook. Pozwala komponentom funkcyjnym na dodawanie stanu do komponentów.
import { useState } from "react"; // Pamiętaj o importowaniu tylko tego, czego potrzebujesz
function MyComponent() {
// Deklaracja stanu 'isOn' z początkową wartością 'false'
// 'isOn' to bieżąca wartość stanu, 'setIsOn' to funkcja do jej aktualizacji
const [isOn, setIsOn] = useState(false);
// Funkcja zmieniająca stan
const toggleStatus = () => {
setIsOn((prev) => !prev); // Zmieniamy stan na przeciwny
};
return (
<div>
<p>Status: {isOn ? "On" : "Off"}</p>
<button onClick={toggleStatus}>Toggle</button>
</div>
);
}
Za każdym razem, gdy wywołasz setIsOn
, komponent MyComponent
zostanie ponownie wyrenderowany z nową wartością stanu isOn
.
>>>useEffect
useEffect
to Hook, który pozwala na wykonywanie efektów pobocznych (side effects) w komponentach funkcyjnych. Efekty poboczne to operacje, które wchodzą w interakcję ze światem zewnętrznym, takie jak:
- Pobieranie danych z API 🌐
- Subskrypcje zdarzeń (np. nasłuchiwanie kliknięć)
- Bezpośrednia manipulacja DOM (rzadziej potrzebna w React)
- Ustawianie timerów
useEffect
przyjmuje dwa argumenty: funkcję, która zawiera logikę efektu, oraz tablicę zależności (dependency array).
import { useState, useEffect } from "react"; // Importujemy potrzebne Hooki
function FetchedData() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
// useEffect uruchomi się po pierwszym renderowaniu i za każdym razem,
// gdy zmieni się któraś z wartości w tablicy zależności (tutaj: pusta tablica oznacza tylko raz)
useEffect(() => {
// Symulacja pobierania danych
setTimeout(() => {
setData("Data fetched from API! 👍");
setLoading(false);
}, 2000); // Po 2 sekundach
// Opcjonalnie: funkcja czyszcząca (cleanup function)
return () => {
console.log("Component odmontowany lub efekt uruchomiony ponownie.");
};
}, []); // Pusta tablica zależności: efekt uruchamia się tylko raz (jak componentDidMount)
if (loading) {
return <p>Loading data... ⏳</p>;
}
return <h2>{data}</h2>;
}
useEffect
bez tablicy zależności (useEffect(() => { ... });
) uruchamia się po każdym renderowaniu. Z pustą tablicą (useEffect(() => { ... }, []);
) uruchamia się tylko raz, po pierwszym renderowaniu. Z tablicą zależności (useEffect(() => { ... }, [variable1, variable2]);
) uruchamia się, gdy wartości w tablicy ulegną zmianie.
>>Podsumowanie
Gratulacje! Zrobiłeś/aś pierwsze kroki w świecie Reacta. 🎉 Wiesz już, że React to potężna biblioteka do budowania interfejsów użytkownika w oparciu o komponenty. Zrozumiałeś/aś kluczowe koncepcje takie jak JSX, propsy, stan oraz Wirtualny DOM. Poznałeś/aś również komponenty funkcyjne i podstawowe Hooki (useState
, useEffect
), które są fundamentem nowoczesnego Reacta. Nauczyłeś/aś się także, jak szybko inicjować projekty za pomocą Vite.
To dopiero początek przygody! React oferuje znacznie więcej możliwości, takich jak:
- Routing (np. React Router) 🧭
- Zaawansowane zarządzanie stanem (np. Context API, Redux, Zustand)
- Formularze i ich walidacja
- Obsługa API i asynchroniczności
- Testowanie komponentów
Zachęcam do dalszego eksperymentowania i budowania własnych projektów. Praktyka to najlepszy sposób na naukę! 🚀
>>Zadania do wykonania
Poniższe zadania pomogą Ci utrwalić wiedzę o podstawach Reacta. Stwórz nowy projekt React z Vite, a następnie wykonaj w nim poniższe zadania, tworząc osobne komponenty. Pamiętaj, aby importować tylko te Hooki i funkcje, których potrzebujesz!
>>>Zadanie 1: Komponent Powitania
Stwórz nowy komponent funkcyjny o nazwie Welcome
, który:
- Przyjmuje jeden prop o nazwie
name
. - Wyświetla nagłówek
<h1>
z tekstem "Hello, [name]!" - Wykorzystaj ten komponent dwukrotnie w komponencie
App.jsx
, przekazując różne imiona.
Pokaż rozwiązanie
// src/components/Welcome.jsx
// Stwórz nowy katalog 'components' w 'src' dla lepszej organizacji
function Welcome(props) {
// Komponent wyświetlający powitanie na podstawie propsów
return <h1>Hello, {props.name}! 👋</h1>;
}
export default Welcome;
// src/App.jsx
import Welcome from './components/Welcome'; // Pamiętaj o poprawnej ścieżce importu!
function App() {
return (
<div>
<Welcome name="Alice" />
<Welcome name="Bob" />
<Welcome name="World" />
</div>
);
}
export default App;
>>>Zadanie 2: Licznik z przyciskiem
Stwórz nowy komponent funkcyjny o nazwie Counter
, który:
- Używa Hooka
useState
do zarządzania stanem licznika (początkowa wartość0
). - Wyświetla aktualną wartość licznika w akapicie (
<p>
). - Posiada dwa przyciski: jeden do zwiększania licznika o 1, drugi do zmniejszania licznika o 1.
Pokaż rozwiązanie
// src/components/Counter.jsx
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // Deklaracja stanu licznika
const increment = () => {
// Funkcja zwiększająca licznik
setCount(prevCount => prevCount + 1); // Najlepsza praktyka: używaj funkcji do aktualizacji stanu
};
const decrement = () => {
// Funkcja zmniejszająca licznik
setCount(prevCount => prevCount - 1);
};
return (
<div>
<h2>My Counter</h2>
<p>Current value: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
}
export default Counter;
// src/App.jsx (example usage)
import Counter from './components/Counter';
function App() {
return (
<div style={{ textAlign: 'center', marginTop: '50px' }}>
<Counter />
</div>
);
}
export default App;
>>>Zadanie 3: Lista elementów
Stwórz nowy komponent funkcyjny o nazwie ShoppingList
, który:
- Używa Hooka
useState
do przechowywania tablicy elementów zakupów (początkowo pusta, np.[]
). - Wyświetla te elementy jako nieuporządkowaną listę (
<ul>
). - Pobierz dane z tablicy wewnątrz
useEffect
po pierwszym renderowaniu komponentu, symulując pobieranie z API. W międzyczasie wyświetlaj "Loading list...".
Pokaż rozwiązanie
// src/components/ShoppingList.jsx
import { useState, useEffect } from 'react';
function ShoppingList() {
const [items, setItems] = useState([]); // Stan dla listy zakupów
const [loading, setLoading] = useState(true); // Stan dla statusu ładowania
useEffect(() => {
// Symulacja pobierania danych z API
setTimeout(() => {
const fetchedItems = ['Milk 🥛', 'Bread 🍞', 'Eggs 🥚', 'Coffee ☕'];
setItems(fetchedItems); // Ustawienie pobranych danych
setLoading(false); // Zmiana statusu ładowania
}, 1500); // Symulacja 1.5 sekundy czasu ładowania
}, []); // Pusta tablica zależności: efekt uruchamia się tylko raz po zamontowaniu komponentu
if (loading) {
return <p>Loading shopping list... ⏳</p>; // Wyświetlanie komunikatu ładowania
}
return (
<div>
<h2>Your Shopping List</h2>
<ul>
{items.map((item, index) => (
// Renderowanie każdego elementu listy
<li key={index}>{item}</li> // Prop 'key' jest ważny dla list w React!
))}
</ul>
</div>
);
}
export default ShoppingList;
// src/App.jsx (example usage)
import ShoppingList from './components/ShoppingList';
function App() {
return (
<div style={{ textAlign: 'center', marginTop: '50px' }}>
<ShoppingList />
</div>
);
}
export default App;