·
Pytania i odpowiedzi React
React — interview Q&A
40 Pytań
0 Znanych
Zestaw 40 pytań rekrutacyjnych z React pogrupowanych w 5 kategorii: podstawy, hooks, state management, performance oraz wzorce i architektura. Kliknij pytanie, by zobaczyć odpowiedź.
🔍
40 pytań
🔍
Brak wyników dla podanej frazy
1 Czym jest React i na czym polega jego model deklaratywny? ✓ ▶

React to biblioteka JavaScript do budowania interfejsów użytkownika, stworzona przez Meta. Nie jest pełnym frameworkiem — odpowiada wyłącznie za warstwę widoku (V w MVC).

Model deklaratywny polega na tym, że opisujesz jaki ma być stan UI, a nie jak do niego dojść. React sam optymalnie oblicza i aplikuje różnicę (diffing). W modelu imperatywnym (np. vanilla JS) sam manipulujesz DOM-em krok po kroku — React to ukrywa za warstwą abstrakcji Virtual DOM.

Podstawy
2 Czym jest Virtual DOM i jak działa reconciliation? ✓ ▶

Virtual DOM to lekka, in-memory reprezentacja drzewa DOM w JavaScript. Przy każdym renderze React tworzy nowe drzewo VDOM i porównuje je z poprzednim.

Reconciliation to algorytm obliczający minimalny zestaw zmian (diff) potrzebny do aktualizacji prawdziwego DOM. React stosuje heurystyki: różne typy elementów = pełne zastąpienie; ta sama lista = użyj key do identyfikacji. Wynik diff trafia do Reacta DOM (renderer), który aplikuje zmiany w jednej sekwencji — minimalizując kosztowne operacje na DOM.

Podstawy
4 Czym jest JSX i jak jest przetwarzany? ✓ ▶

JSX (JavaScript XML) to rozszerzenie składni JS pozwalające pisać markup podobny do HTML wewnątrz kodu JavaScript. Nie jest częścią standardu JS — transpilowany przez Babel/SWC.

Każdy tag JSX jest zamieniany na wywołanie React.createElement(type, props, ...children) (przed React 17) lub importowany transform jsx() (React 17+, automatyczny import). JSX to cukier składniowy — absolutnie nic magicznego; to zwykłe wywołania funkcji zwracające obiekty opisujące węzły VDOM.

// JSX const el = <Button color="blue">Kliknij</Button>; // Po transpilacji const el = jsx(Button, { color: "blue" }, "Kliknij");
Podstawy
5 Czym są props i jak działają w React? ✓ ▶

Props (properties) to dane przekazywane od komponentu-rodzica do komponentu-dziecka. Są immutable z perspektywy dziecka — komponent nie powinien modyfikować własnych props.

Przepływ danych w React jest jednokierunkowy (one-way data flow): dane płyną w dół przez props. Dziecko może komunikować się z rodzicem przez przekazane callback functions (props będące funkcjami). Props mogą być dowolnym typem JS: string, number, object, tablica, funkcja, a nawet inny komponent React.

Podstawy
6 Dlaczego key jest ważny przy renderowaniu list? ✓ ▶

key to specjalny prop pomagający Reactowi identyfikować, które elementy listy zmieniły się, zostały dodane lub usunięte podczas reconciliation.

Bez stabilnych kluczy React porównuje elementy pozycyjnie — gdy kolejność się zmieni (np. element dodany na początku), React niepotrzebnie niszczy i odtwarza wszystkie węzły poniżej. Z kluczem React wie dokładnie który element jest który. Czego unikać: index tablicy jako key przy listach, które mogą być sortowane/filtrowane (prowadzi do bugów ze stanem komponentów). Używaj stabilnych, unikalnych ID z danych.

Podstawy
7 Co to jest lifting state up i kiedy go stosować? ✓ ▶

Lifting state up (wynoszenie stanu w górę) polega na przeniesieniu współdzielonego stanu do najbliższego wspólnego przodka komponentów, które go potrzebują.

Stosuj gdy: dwa rodzeństwa muszą mieć zsynchronizowany stan, formularz w wielu komponentach operuje na tych samych danych, komponent-dziecko musi zmienić dane widoczne w rodzeństwie. Alternatywą przy głębokim drzewie jest Context API lub zewnętrzny state manager (Zustand, Redux), żeby uniknąć prop drilling.

Podstawy
8 Czym jest React StrictMode i do czego służy? ✓ ▶

StrictMode to narzędzie deweloperskie (nie wpływa na produkcję). Owija część lub całość drzewa komponentów i aktywuje dodatkowe sprawdzenia.

Co robi: podwójnie wywołuje funkcje komponentów, useState settery i useReducer reducery (w React 18 — aby wykryć efekty uboczne w renderze); montuje i odmontowuje efekty dwukrotnie (aby wykryć brakujące cleanup w useEffect); ostrzega o przestarzałych API. Bardzo przydatny przy migracji do React 18 i wykrywaniu nieoczekiwanych side effects.

Podstawy
9 Jak działa useState i dlaczego aktualizacje stanu są asynchroniczne? ✓ ▶

useState zwraca parę: aktualną wartość stanu i funkcję setter. Wywołanie settera planuje (schedules) re-render — React nie aktualizuje zmiennej natychmiast w bieżącej funkcji.

Aktualizacje są wsadowane (batched): React grupuje wiele setterów wywołanych w jednym handlerze zdarzeń w jeden re-render (React 18 rozszerzył batching na asynchrniczne operacje). Dlatego zaraz po setCount(count + 1) zmienna count ma stare wartości. Gdy nowy stan zależy od poprzedniego, używaj formy funkcyjnej: setCount(prev => prev + 1).

Hooks
10 Jak działa useEffect i co oznacza tablica zależności? ✓ ▶

useEffect synchronizuje komponent z zewnętrznym systemem: API calls, subskrypcje, timery, manipulacja DOM. Uruchamia się po malowaniu ekranu.

Tablica zależności kontroluje kiedy efekt się ponawia: brak tablicy → po każdym renderze; pusta tablica [] → tylko przy montowaniu; z wartościami [dep1, dep2] → gdy zmieni się którakolwiek zależność. Funkcja zwrócona z useEffect to cleanup — React wywołuje ją przed następnym efektem lub odmontowaniem (anuluj subskrypcje, clearTimeout itp.). Brakujący cleanup = memory leak.

Hooks
11 Czym różni się useCallback od useMemo? ✓ ▶

useMemo zapamiętuje wynik wywołania funkcji i zwraca tę samą wartość dopóki zależności się nie zmienią. Używany do kosztownych obliczeń:

const sortedList = useMemo(() => items.sort(...), [items]);

useCallback zapamiętuje samą funkcję (referencję). Przydatny gdy przekazujesz callback do zoptymalizowanego komponentu dziecka (React.memo) — bez useCallback przy każdym renderze rodzica powstaje nowa referencja funkcji, co powoduje re-render dziecka.

const handleClick = useCallback(() => doSomething(id), [id]);

Ważne: oba mają koszt — nie używaj ich wszędzie, tylko gdy masz mierzalny problem z wydajnością.

Hooks
12 Do czego służy useRef i kiedy go używać? ✓ ▶

useRef zwraca mutowalny obiekt { current: initialValue }. Kluczowa właściwość: zmiana ref.current nie powoduje re-renderu.

Dwa główne zastosowania: 1. Dostęp do węzła DOM — <input ref={inputRef} />, potem inputRef.current.focus(); 2. Przechowywanie wartości między renderami bez wywoływania re-renderu — np. poprzednia wartość propsa, ID timeoutu, flaga czy komponent zamontowany. Używaj useRef gdy potrzebujesz "zmiennej instancji" — czegoś trwałego między renderami, ale nie powodującego renderów.

Hooks
13 Kiedy użyć useReducer zamiast useState? ✓ ▶

useReducer sprawdza się gdy: stan to złożony obiekt z wieloma polami aktualizowanymi razem, kolejna wartość stanu zależy od wielu poprzednich wartości jednocześnie, logika aktualizacji jest skomplikowana lub chcesz ją testować w izolacji.

Pattern: const [state, dispatch] = useReducer(reducer, initialState). Reducer to czysta funkcja (state, action) => newState — łatwa do unit testowania. Dobra zasada: gdy masz 3+ powiązanych useState, które zmieniają się razem, rozważ konsolidację do useReducer. Połączony z Context zastępuje podstawowe potrzeby Redux.

Hooks
14 Czym są custom hooks i jakie są zasady rządzące hookami? ✓ ▶

Custom hook to funkcja JS zaczynająca się od use, która może wywoływać inne hooki. Służy do ekstrakcji i reużycia logiki stanowej między komponentami (np. useFetch, useLocalStorage, useDebounce).

Zasady hooków (Rules of Hooks): 1. Wywołuj hooki tylko na poziomie top-level — nigdy wewnątrz pętli, warunków lub zagnieżdżonych funkcji; 2. Wywołuj hooki tylko z komponentów React lub custom hooków — nie z czystych funkcji JS. Zasady te są wymuszane przez ESLint plugin eslint-plugin-react-hooks. Naruszenie powoduje błędy związane z kolejnością hooków między renderami.

Hooks
15 Co to jest useLayoutEffect i kiedy go używać zamiast useEffect? ✓ ▶

useLayoutEffect ma identyczną sygnaturę jak useEffect, ale uruchamia się synchronicznie po mutacjach DOM, ale przed malowaniem ekranu. Blokuje browser paint do czasu zakończenia efektu.

Kiedy używać: gdy efekt musi odczytać layout DOM (np. zmierzyć element, getBoundingClientRect) i od razu zmodyfikować DOM, zanim użytkownik cokolwiek zobaczy — unikasz migotania (flash). Przykłady: tooltips, popovers pozycjonowane względem elementu, animacje wejścia bazujące na rozmiarze. Domyślnie używaj useEffect — useLayoutEffect tylko gdy widzisz migotanie UI.

Hooks
16 Co nowego przynosi React 19 w kwestii hooków? ✓ ▶

React 19 wprowadził kilka nowych hooków upraszczających wzorce, które wcześniej wymagały dużo boilerplate:

  • useActionState — zarządza stanem i pending/error formularzy opartych na Server Actions lub zwykłych funkcjach async
  • useFormStatus — dostęp do statusu (pending) formularza nadrzędnego bez prop-drilling
  • useOptimistic — optymistyczne aktualizacje UI: natychmiast wyświetl zaktualizowany stan, cofnij przy błędzie
  • use(promise) — czytanie Promise lub Context wewnątrz render z obsługą Suspense

Dodatkowo React Compiler (RC) automatycznie memoizuje komponenty — w przyszłości useMemo / useCallback staną się zbędne.

Hooks
17 Czym jest Context API i jakie ma ograniczenia? ✓ ▶

Context API pozwala przekazywać dane przez drzewo komponentów bez ręcznego prop drilling na każdym poziomie. Tworzysz kontekst (createContext), owijasz drzewo Providerem z wartością, konsumentujesz przez useContext.

Ograniczenia wydajnościowe: każda zmiana wartości Providera powoduje re-render wszystkich konsumentów tego kontekstu — nawet jeśli używają tylko fragmentu wartości. To sprawia, że Context słabo nadaje się do często zmieniającego się stanu globalnego (np. pozycja kursora). Rozwiązania: dzielenie kontekstu na mniejsze, useMemo na wartości, lub biblioteki jak Zustand/Jotai obsługujące selektywne subskrypcje.

State Management
18 Czym jest Redux i jaki jest jego podstawowy przepływ danych? ✓ ▶

Redux to biblioteka do przewidywalnego zarządzania stanem oparta na 3 zasadach: jedno źródło prawdy (single store), stan jest read-only (zmiana tylko przez actions), zmiany opisane czystymi funkcjami (reducers).

Przepływ: UI dispatch → Action → Reducer (czysta funkcja state + action → new state) → Store → UI re-render. Dziś standardem jest Redux Toolkit (RTK), który eliminuje boilerplate: createSlice generuje actions i reducer razem, createAsyncThunk obsługuje async, RTK Query zastępuje react-query dla cache API. Redux warto stosować przy złożonym, współdzielonym stanie w dużych teamach.

State Management
19 Czym jest Zustand i dlaczego zyskał popularność? ✓ ▶

Zustand to minimalistyczna biblioteka stanu (~1KB). API oparte na jednej funkcji create — nie ma Provider, boilerplate, ani skomplikowanych reducerów.

const useStore = create((set) => ({ count: 0, increment: () => set((s) => ({ count: s.count + 1 })), }));

Kluczowa zaleta: selektywne subskrypcje — komponent re-renderuje się tylko gdy zmieni się ta część store, którą konsumuje (np. useStore(s => s.count)). Nie ma problemu z wydajnością Context. Popularność wynika z prostoty, małego rozmiaru i braku Provider hell. Dobry wybór dla małych-średnich aplikacji bez potrzeby DevTools Redux.

State Management
20 Co to jest server state i czym różni się od client state? ✓ ▶

Client state to dane żyjące tylko w przeglądarce: stan UI (czy modal otwarty), dane formularzy, preferencje użytkownika. Właścicielem jest aplikacja frontendowa.

Server state to dane przychodzące z serwera: listy użytkowników, produkty, posty. Są asynchroniczne, wspólne (inni użytkownicy mogą je zmieniać) i outdate'ują się. Wymaga zarządzania: cache, refetching, loading/error states, stale-while-revalidate. Biblioteki jak TanStack Query (react-query), SWR lub RTK Query zarządzają server state — Redux/Zustand są złym wyborem dla danych serwerowych, bo nie mają wbudowanego caching/invalidation.

State Management
21 Czym jest TanStack Query (react-query) i jakie problemy rozwiązuje? ✓ ▶

TanStack Query to biblioteka zarządzająca server state: fetching, caching, synchronizacja i aktualizacja danych asynchronicznych. Zastępuje ręczne useEffect + useState do fetch.

Rozwiązuje: automatyczne cachowanie (deduplika requestów), background refetching (dane świeże przy powrocie na tab), stale-while-revalidate, loading/error/success states out-of-box, invalidacja i refetch po mutacji, infinite scroll, optimistic updates, retry logic. Hook useQuery(key, fetcher) + useMutation to dziś standard dla zapytań API w React bez SSR frameworka.

State Management
22 Dlaczego nie należy mutować stanu bezpośrednio w React? ✓ ▶

React wykrywa zmiany stanu przez porównanie referencji (Object.is). Jeśli bezpośrednio zmutuj obiekt/tablicę, referencja pozostaje ta sama — React nie widzi zmiany i nie re-renderuje komponentu.

Poprawne podejście: zawsze tworzyć nowe obiekty/tablice: setState([...prev, newItem]), setState({...prev, field: value}). Dla głęboko zagnieżdżonych struktur pomocna jest biblioteka Immer (używana wewnętrznie przez Redux Toolkit) — pozwala pisać "mutujący" kod, który w rzeczywistości produkuje nową immutable kopię.

State Management
23 Co to jest prop drilling i jak go unikać? ✓ ▶

Prop drilling to przekazywanie props przez wiele poziomów drzewa komponentów tylko po to, żeby dotarły do głęboko zagnieżdżonego komponentu — pośrednie komponenty nie korzystają z tych props, tylko je "przesyłają".

Rozwiązania: Context API — dla rzadko zmieniających się danych (theme, locale, auth user); Zustand/Jotai/Redux — globalny store z selektywnymi subskrypcjami; Component composition — przekazywanie komponentów jako children lub props zamiast danych; renderowanie bliżej źródła — czy na pewno stan musi żyć tak wysoko? Często prop drilling można naprawić, przenosząc stan niżej lub kolocując komponent bliżej danych.

State Management
24 Czym jest Jotai i kiedy wybrać go zamiast Zustand? ✓ ▶

Jotai to atomowy model stanu inspirowany Recoilem. Zamiast jednego store definiujesz atomowe jednostki stanu (atom), które komponenty konsumują niezależnie — każdy atom to osobna subskrypcja.

Kiedy Jotai vs Zustand: Jotai lśni przy wielu niezależnych, granularnych jednostkach stanu (np. każda komórka w arkuszu kalkulacyjnym, każdy węzeł w edytorze); model atomowy jest naturalny gdy stan ma zależności między atomami (derivedAtom). Zustand lepiej gdy masz jeden zintegrowany store z wieloma akcjami i wyraźną strukturą — bardziej zbliżony do Redux, prostszy mental model dla teamów znających Redux.

State Management
25 Czym jest React.memo i kiedy go stosować? ✓ ▶

React.memo to HOC, który opakowuje komponent funkcyjny i zapobiega jego re-renderowi jeśli props nie zmieniły się (shallow comparison). Odpowiednik PureComponent dla klas.

Kiedy używać: komponent renderuje się często, a rodzic re-renderuje się często; komponent jest kosztowny do renderowania; props rzadko się zmieniają. Czego unikać: owijania każdego komponentu (overhead memoizacji może być większy niż koszt re-renderu dla lekkich komponentów); pamiętaj że inline functions i object literals jako props tworzą nowe referencje przy każdym renderze rodzica — para React.memo + useCallback/useMemo jest często potrzebna razem.

Performance
26 Co to jest code splitting i lazy loading w React? ✓ ▶

Code splitting to podział bundle JS na mniejsze chunki ładowane na żądanie. Bez niego cały kod aplikacji trafia do jednego dużego pliku — nawet strony nigdy nie odwiedzone przez użytkownika.

W React: React.lazy(() => import('./Component')) + <Suspense fallback={...}>. Webpack/Vite automatycznie tworzą osobny chunk dla dynamicznie importowanych modułów. Strategie: route-based splitting (każda trasa = osobny chunk — najpopularniejsze), component-based splitting (ciężkie komponenty jak edytory, wykresy), vendor splitting (osobny chunk dla bibliotek). Narzędzie: @loadable/component dla SSR.

Performance
27 Czym jest windowing / virtualizacja list? ✓ ▶

Windowing (wirtualizacja) polega na renderowaniu tylko tych elementów listy, które są aktualnie widoczne w viewporcie. Zamiast 10 000 węzłów DOM — renderujesz np. 20-30 i zmieniasz ich zawartość przy scrollowaniu.

Bez wirtualizacji długa lista (tysiące pozycji) = tysiące węzłów DOM = wolny render, wolny scroll, duże zużycie pamięci. Biblioteki: react-window (lżejsza, API prostsze), react-virtual / TanStack Virtual (bez DOM headless, elastyczniejsze), react-virtuoso (obsługuje zmienną wysokość wierszy out-of-box). Niezbędne przy listach >500 elementów z danymi dynamicznymi.

Performance
28 Co to jest React Profiler i jak debugować wolne rendery? ✓ ▶

React Profiler to narzędzie dostępne w React DevTools. Nagrywa sesję renderów i pokazuje: które komponenty renderowały się, ile razy i jak długo. Pozwala zidentyfikować "expensive renders" i zbędne re-rendery.

Proces debugowania: 1. Nagraj sesję w DevTools Profiler; 2. Znajdź komponenty renderujące się często lub długo (czerwone/żółte bary); 3. Sprawdź dlaczego się renderują (zmieniony state/context/props); 4. Zastosuj React.memo, useMemo, useCallback lub podziel kontekst. Komponent <Profiler onRender={callback}> pozwala mierzyć wydajność programowo w produkcji.

Performance
29 Czym jest React Concurrent Mode i co to są Transitions? ✓ ▶

Concurrent Mode (React 18+) pozwala Reactowi przerwać, wznowić i porzucić rendery. Zamiast blokowania głównego wątku na duży render, React może go "pauzować" aby obsłużyć pilniejsze zdarzenia (np. kliknięcia).

startTransition / useTransition oznaczają aktualizację stanu jako niepilną (low-priority). React może opóźnić tę aktualizację jeśli przychodzą pilniejsze zdarzenia. Przykład: wpisywanie w wyszukiwarce — aktualizacja inputa jest pilna, filtrowanie 10 000 wyników to transition. useDeferredValue — podobny efekt dla wartości z zewnątrz.

Performance
30 Czym jest Suspense i jak obsługuje stany ładowania? ✓ ▶

Suspense pozwala deklaratywnie określić co wyświetlić gdy komponent "czeka" na coś (lazy import, dane). Komponent dziecko rzuca Promise — React łapie go i wyświetla fallback aż do rozwiązania.

Zastosowania: Lazy loading komponentów (React.lazy + Suspense); Data fetching (React 19 use(promise), Next.js 13+ Server Components, Relay, TanStack Query v5 z experimentalSuspense). Zagnieżdżone Suspense boundary pozwalają pokazywać skeleton UI na różnych poziomach granularności — zamiast jednego globalnego spinnera, każda sekcja ładuje się niezależnie.

Performance
31 Czym jest Server-Side Rendering (SSR) i jak różni się od CSR? ✓ ▶

CSR (Client-Side Rendering): przeglądarka pobiera pusty HTML + JS bundle, JS renderuje całą aplikację w przeglądarce. Wolniejszy FCP (First Contentful Paint), słabszy SEO, ale szybka nawigacja po pierwszym ładowaniu.

SSR: serwer renderuje HTML przy każdym żądaniu i wysyła gotową stronę. Szybszy FCP, dobre SEO, ale każde żądanie wymaga pracy serwera. SSG (Static Site Generation): HTML generowany w build time — ultra-szybki, idealny dla blogów/dokumentacji. ISR (Incremental Static Regeneration, Next.js): SSG z możliwością regeneracji strony w tle co N sekund. Nowoczesne frameworki (Next.js, Remix) mieszają te podejścia per-route.

Performance
32 Co to są React Server Components? ✓ ▶

React Server Components (RSC, React 18+/Next.js 13+) to komponenty renderowane wyłącznie po stronie serwera — ich kod nigdy nie trafia do klienta. Mogą bezpośrednio czytać z bazy danych, systemu plików, wywoływać API bez fetch po stronie klienta.

Kluczowe cechy: zero bundle size (kod pozostaje na serwerze), brak dostępu do hooków (useState, useEffect) — są statyczne; mogą zawierać Client Components oznaczone "use client". Korzyści: mniejszy bundle, dane bliżej źródła, naturalny waterfall fetching. Granica: RSC → Client Component można przekraczać przez props, ale tylko z serializable values (nie funkcje).

Performance
33 Co to są Higher-Order Components (HOC) i kiedy je stosować? ✓ ▶

HOC to funkcja przyjmująca komponent i zwracająca nowy, ulepszony komponent. Pattern reużycia logiki poprzedni generacji Reacta — dziś częściowo zastąpiony przez custom hooks.

Przykłady: withAuth(Component) (redirect jeśli nie zalogowany), withLogger(Component) (logowanie props), connect() z Redux. HOC nadal ma sens gdy: dodajesz logikę do komponentu, który nie możesz modyfikować (biblioteki zewnętrzne); potrzebujesz wstrzyknąć props na podstawie kontekstu. Wady: wrapper hell (głęboka hierarchia HOC), nieintuicyjne debugowanie, konflikty nazw props. Custom hooks są preferowane gdy to możliwe.

Wzorce i architektura
34 Co to jest Compound Components Pattern? ✓ ▶

Compound Components to wzorzec, w którym rodzic i dzieci komunikują się przez niejawny, wspólny stan — bez prop drilling. Komponenty "wie" o sobie nawzajem przez Context.

Przykład: komponent <Select> z dziećmi <Select.Option>. Select zarządza stanem (który option wybrany), każde Option przez useContext wie o stanie rodzica i może je zmieniać. Użytkownik API (developer) ma pełną kontrolę nad strukturą HTML i stylami — elastyczność bez utraty funkcjonalności. Używany w: Radix UI, Headless UI, Reach UI, własne design systemy.

Wzorce i architektura
35 Czym jest Error Boundary i jak obsługiwać błędy w React? ✓ ▶

Error Boundary to komponent klasowy implementujący componentDidCatch i getDerivedStateFromError. Łapie błędy JS w poddrzewie komponentów i wyświetla fallback UI zamiast crashować całą aplikację.

Ważne: Error Boundaries nie łapią błędów w: event handlers (tam użyj try/catch), asynchronicznym kodzie (setTimeout, promises), SSR, samej Error Boundary. React 19 planuje wsparcie dla funkcyjnych Error Boundaries. Biblioteka react-error-boundary daje wygodne API z reset capabilities: <ErrorBoundary FallbackComponent={Error} onReset={resetApp}>. Stosuj granularnie — różne boundary dla różnych sekcji UI.

Wzorce i architektura
36 Co to są React Portals i kiedy ich używać? ✓ ▶

Portals pozwalają renderować dziecko komponentu w innym węźle DOM niż rodzic — najczęściej bezpośrednio w document.body. Tworzone przez ReactDOM.createPortal(child, container).

Kiedy używać: modals/dialogi — unikają problemów z overflow: hidden i z-index rodziców; tooltips/popovers — muszą wychodzić poza scrollowalny kontener; floating notifications. Ważne: portal jest poza DOM-em rodzica, ale nadal wewnątrz drzewa React — eventy bąbelkują przez drzewo React normalnie, nie przez drzewo DOM.

Wzorce i architektura
37 Czym jest Controlled vs Uncontrolled component? ✓ ▶

Controlled component: wartość formularza jest zarządzana przez React state. Każda zmiana pola → handler → setState → re-render z nową wartością. React jest "jedynym źródłem prawdy". Pełna kontrola: walidacja w locie, formatowanie, zablokowane znaki.

Uncontrolled component: DOM sam zarządza wartością, React czyta ją przez ref (inputRef.current.value) na żądanie (np. przy submit). Mniej kodu, lepsza wydajność dla bardzo dużych formularzy. Biblioteka React Hook Form używa modelu uncontrolled z ref-based approach dla maksymalnej wydajności przy minimalnym kodzie — dlatego ogranicza re-rendery do minimum.

Wzorce i architektura
38 Co to jest React Router i jak działa client-side routing? ✓ ▶

React Router v6 to najpopularniejsza biblioteka routingu dla React. Client-side routing działa przez History API przeglądarki — zmiana URL nie powoduje przeładowania strony, React renderuje odpowiedni komponent.

Kluczowe elementy: <BrowserRouter>, <Routes> + <Route path="" element={} />, useNavigate(), useParams(), useSearchParams(), useLocation(). React Router v6.4+ dodaje Data API: loader (fetch danych przed renderem), action (obsługa form submit) — upodabniając do Remix. TanStack Router zyskuje popularność jako type-safe alternatywa z pełną inferencją TypeScript.

Wzorce i architektura
39 Jak testować komponenty React? ✓ ▶

Ekosystem testowania React: Vitest/Jest — test runner; React Testing Library (RTL) — renderowanie i interakcja z komponentami w sposób zbliżony do użytkownika (getByRole, userEvent.click); MSW (Mock Service Worker) — mockowanie API na poziomie sieciowym; Playwright/Cypress — testy E2E.

Filozofia RTL: "Test the way users use your software" — nie testuj implementacji (nazwy stanów, nazwy metod), testuj zachowanie (tekst wyświetlony, dostępność elementu, reakcja na kliknięcie). Priorytet selektorów: role > label > text > testId. Custom hooks testuje się osobno przez renderHook() z RTL.

Wzorce i architektura
40 Czym jest Next.js i jaką wartość dodaje nad czystym React? ✓ ▶

Next.js to pełnoprawny framework oparty na React. Dodaje: file-based routing (folder = route), SSR/SSG/ISR/RSC out-of-box, API routes (backend w tym samym projekcie), Image Optimization, font optimization, built-in bundler (Turbopack), middleware, deployment na Vercel bez konfiguracji.

App Router (Next.js 13+) to podejście oparte na Server Components domyślnie — komponenty są SC chyba że oznaczymy "use client". Pozwala colocować Server Actions (server-side mutations) bezpośrednio z komponentami. Next.js wybrałbyś dla: aplikacji produkcyjnych wymagających SEO, aplikacji fullstack z jedną bazą kodu, gdy chcesz najlepsze możliwe Core Web Vitals out-of-box.

Wzorce i architektura