jakubszpil

Wprowadzenie do Reacta

📆
/
11 minut czytania

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

  1. Czym jest React?
  2. Dlaczego React? Główne zalety
  3. Podstawowe pojęcia w React
  4. Tworzenie pierwszej aplikacji React z Vite
  5. Komponenty funkcyjne i Hooki (Hooks)
  6. Podsumowanie
  7. 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:

  1. 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".
  2. 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.
  3. 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. ⚡️
  4. 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ą.
  5. 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. 🤝
  6. 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?

  1. Kiedy stan aplikacji się zmienia, React tworzy nowy Wirtualny DOM.
  2. Porównuje go z poprzednim Wirtualnym DOM (proces zwany "diffing").
  3. Oblicza minimalną liczbę zmian potrzebnych do zaktualizowania prawdziwego DOM.
  4. 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:

  1. Upewnij się, że masz zainstalowany Node.js (wraz z npm lub yarn) na swoim komputerze.
  2. Otwórz terminal (lub wiersz poleceń).
  3. Uruchom polecenie:
    npm create vite@latest
    
    lub
    yarn create vite
    
  4. Zostaniesz poproszony/a o podanie nazwy projektu (np. my-react-app).
  5. Następnie wybierz framework: React.
  6. Wybierz wariant: JavaScript (lub TypeScript, jeśli znasz).
  7. Po zakończeniu instalacji, przejdź do katalogu projektu:
    cd my-react-app
    
  8. Zainstaluj zależności:
    npm install
    
    lub
    yarn install
    
  9. Uruchom aplikację:
    npm run dev
    
    lub
    yarn dev
    
    To uruchomi serwer deweloperski, a Twoja aplikacja będzie dostępna pod adresem 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:

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:

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:

  1. Przyjmuje jeden prop o nazwie name.
  2. Wyświetla nagłówek <h1> z tekstem "Hello, [name]!"
  3. 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:

  1. Używa Hooka useState do zarządzania stanem licznika (początkowa wartość 0).
  2. Wyświetla aktualną wartość licznika w akapicie (<p>).
  3. 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:

  1. Używa Hooka useState do przechowywania tablicy elementów zakupów (początkowo pusta, np. []).
  2. Wyświetla te elementy jako nieuporządkowaną listę (<ul>).
  3. 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;

Quiz: Podstawy Reacta

Pytanie 1 z 5

Czym jest React?

Widzisz jakiś błąd, bądź literówkę? Chcesz coś poprawić?✏️ Przejdź do edycji tego pliku