← Wszystkie tematy

Pytania rekrutacyjne z zarządzania stanem z odpowiedziami

useState i useReducer, prop drilling, Context, Redux Toolkit, Zustand oraz stan serwerowy: TanStack Query, RTK Query, SWR i loader/action w React Router.

225 pytań na rozmowę rekrutacyjną z tematu Zarządzanie stanem z odpowiedziami i wyjaśnieniami - poziomy Junior, Middle i Senior. Przykładowe pytania, testy online i zadania z kodu.

Pytania według poziomu

Przykładowe pytania

Kilka pytań z każdego poziomu z poprawną odpowiedzią i wyjaśnieniem.

Zarządzanie stanem · Junior

  1. Czym jest „stan” (state) w komponencie React?

    Poprawna odpowiedź: Dane, które zmieniają się w czasie i wpływają na ekran; ich zmiana powoduje ponowny render

    Stan to pamięć komponentu między renderami: wartość licznika, tekst w polu, czy menu jest otwarte. Zwykła zmienna let resetuje się przy każdym renderze, a jej zmiana nie prosi Reacta o odświeżenie UI. Propsy to dane wejściowe tylko do odczytu, należą do rodzica.

  2. Kiedy potrzebna jest funkcyjna forma setCount(c => c + 1) zamiast setCount(count + 1)?

    Poprawna odpowiedź: Gdy nowa wartość zależy od poprzedniej, zwłaszcza przy kilku aktualizacjach z rzędu

    count to migawka bieżącego renderu. Trzy wywołania setCount(count + 1) w jednym handlerze dają +1, a trzy setCount(c => c + 1) - +3: każdy updater dostaje wynik poprzedniego. To samo chroni przed nieaktualnymi domknięciami w timerach i efektach.

  3. Jak usunąć element z id z tablicy w stanie?

    Poprawna odpowiedź: setItems(items.filter(i => i.id !== id))

    Stan aktualizuje się niemutowalnie: filter, map, spread i toSorted tworzą nową tablicę. splice i delete mutują istniejącą, referencja się nie zmienia i React pomija aktualizację.

  4. Po co przekazywać funkcję do useState(() => createInitialTodos())?

    Poprawna odpowiedź: Aby kosztowne obliczenie wykonało się tylko przy pierwszym renderze

    useState(createInitialTodos()) wywołuje funkcję przy każdym renderze, choć wynik jest potrzebny raz. Leniwy inicjalizator useState(createInitialTodos) wywoływany jest tylko przy montowaniu. Musi być synchroniczny i czysty.

Wszystkie 75 pytań z odpowiedziami →

Zarządzanie stanem · Middle

  1. Jak zresetować stan komponentu formularza po zmianie wybranego użytkownika?

    Poprawna odpowiedź: Renderować go z key={userId}, by React utworzył komponent od nowa

    Inny key sprawia, że React traktuje to jako nowy komponent: stary stan jest odrzucany, stosowane są wartości początkowe. Efekt resetujący najpierw renderuje nieaktualne dane, a potem je poprawia - zbędny render i widoczne mignięcie.

  2. Jak przekazać dispatch z useReducer głęboko w drzewo bez prop drillingu?

    Poprawna odpowiedź: Umieścić dispatch w osobnym kontekście; nie zmienia się, więc konsumenci nie renderują się ponownie

    Wzorzec „reducer + kontekst”: jeden kontekst dla state, drugi - dla dispatch. Komponenty, które tylko wysyłają akcje (przyciski, formularze), czytają stabilny kontekst z dispatch i nie renderują się ponownie przy zmianie stanu.

  3. Po co jest trzeci argument init w useReducer(reducer, arg, init)?

    Poprawna odpowiedź: Leniwa inicjalizacja: init(arg) wywoływane jest tylko przy pierwszym renderze

    useReducer(reducer, username, createInitialState) unika ponownego obliczania kosztownego stanu początkowego przy każdym renderze - jak leniwy inicjalizator w useState. init można też wykorzystać do resetowania stanu.

  4. Komponent używa tylko theme z dużego AppContext, ale renderuje się przy każdej zmianie koszyka. Co pomoże?

    Poprawna odpowiedź: Podzielić kontekst na mniejsze według domeny i częstotliwości zmian

    React.memo nie zatrzymuje renderów spowodowanych kontekstem, który czyta komponent. Osobne ThemeContext i CartContext ograniczają aktualizacje do właściwych konsumentów. Przy bardzo częstych aktualizacjach - store z selektorami.

Wszystkie 75 pytań z odpowiedziami →

Zarządzanie stanem · Senior

  1. Dlaczego Redux, Zustand i podobne biblioteki subskrybują przez useSyncExternalStore?

    Poprawna odpowiedź: Gwarantuje spójną migawkę przy renderowaniu współbieżnym (bez tearingu)

    Przy renderowaniu współbieżnym React może wstrzymać render; jeśli zewnętrzny store w tym czasie się zmieni, jedne komponenty odczytają starą wartość, a inne nową. useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) temu zapobiega i obsługuje SSR.

  2. Jaka jest różnica między modelem „subskrypcji selektora” (Redux, Zustand) a Contextem?

    Poprawna odpowiedź: Store powiadamia komponenty, a każdy renderuje się tylko, gdy zmieniła się wybrana przez niego część

    Context nie ma selektorów: każda zmiana value renderuje wszystkich konsumentów. Store'y wykonują selektor każdego subskrybenta i porównują wyniki, więc aktualizacje są punktowe. Biblioteki takie jak use-context-selector emulują to na bazie Contextu.

  3. Gdzie w aplikacji z routingiem najlepiej trzymać stan filtra listy (wyszukiwanie, sortowanie, strona)?

    Poprawna odpowiedź: W parametrach search URL - linkiem można się podzielić, stan przetrwa przeładowanie i działa z „wstecz/dalej”

    URL to też stan. Filtry w ?q=&sort=&page= sprawiają, że linki łatwo udostępniać, a historia ma sens; loadery i klucze zapytań mogą się z nich wywodzić. Wpisywany tekst się debounce'uje i zastępuje (a nie dodaje) wpisy historii przy każdym naciśnięciu.

  4. Jaka klasyfikacja stanu pomaga wybierać narzędzia w dużej aplikacji?

    Poprawna odpowiedź: Cache serwerowy, stan URL, stan formularzy, lokalny stan UI i globalny stan klienta

    Każdy rodzaj ma naturalne miejsce: cache serwerowy - TanStack Query/RTK Query/SWR/loadery; URL - router; formularze - stan lokalny lub biblioteka formularzy; UI - useState; naprawdę globalny stan klienta - Context lub store. Wrzucanie wszystkiego do jednego store'a robi z niego wąskie gardło.

Wszystkie 75 pytań z odpowiedziami →

Testy łączone z tym tematem

Pytania z kilku tematów naraz - jak na rozmowie rekrutacyjnej na konkretne stanowisko.

Zadania z kodu

Napisz rozwiązanie prosto w przeglądarce, a testy od razu je sprawdzą. Klasyka rozmów rekrutacyjnych: debounce, throttle, deepClone, Promise.all, EventEmitter, cache LRU i inne.

Otwórz zadania →