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.
- useState
- useReducer
- Context
- Redux Toolkit
- Zustand
- TanStack Query
- RTK Query
- SWR
- React Router
Pytania według poziomu
Junior
Podstawowe pojęcia i składnia · 50 pytań
Middle
Praktyka, niuanse i optymalizacja · 50 pytań
Senior
Architektura, mechanizmy wewnętrzne, przypadki brzegowe · 50 pytań
Przykładowe pytania
Kilka pytań z każdego poziomu z poprawną odpowiedzią i wyjaśnieniem.
Zarządzanie stanem · Junior
- 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
letresetuje 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. - Kiedy potrzebna jest funkcyjna forma
setCount(c => c + 1)zamiastsetCount(count + 1)?Poprawna odpowiedź: Gdy nowa wartość zależy od poprzedniej, zwłaszcza przy kilku aktualizacjach z rzędu
countto migawka bieżącego renderu. Trzy wywołaniasetCount(count + 1)w jednym handlerze dają +1, a trzysetCount(c => c + 1)- +3: każdy updater dostaje wynik poprzedniego. To samo chroni przed nieaktualnymi domknięciami w timerach i efektach. - Jak usunąć element z
idz tablicy w stanie?Poprawna odpowiedź:
setItems(items.filter(i => i.id !== id))Stan aktualizuje się niemutowalnie:
filter,map, spread itoSortedtworzą nową tablicę.spliceideletemutują istniejącą, referencja się nie zmienia i React pomija aktualizację. - 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 inicjalizatoruseState(createInitialTodos)wywoływany jest tylko przy montowaniu. Musi być synchroniczny i czysty.
Zarządzanie stanem · Middle
- Jak zresetować stan komponentu formularza po zmianie wybranego użytkownika?
Poprawna odpowiedź: Renderować go z
key={userId}, by React utworzył komponent od nowaInny
keysprawia, ż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. - Jak przekazać
dispatchzuseReducergłęboko w drzewo bez prop drillingu?Poprawna odpowiedź: Umieścić
dispatchw osobnym kontekście; nie zmienia się, więc konsumenci nie renderują się ponownieWzorzec „reducer + kontekst”: jeden kontekst dla
state, drugi - dladispatch. Komponenty, które tylko wysyłają akcje (przyciski, formularze), czytają stabilny kontekst z dispatch i nie renderują się ponownie przy zmianie stanu. - Po co jest trzeci argument
initwuseReducer(reducer, arg, init)?Poprawna odpowiedź: Leniwa inicjalizacja:
init(arg)wywoływane jest tylko przy pierwszym renderzeuseReducer(reducer, username, createInitialState)unika ponownego obliczania kosztownego stanu początkowego przy każdym renderze - jak leniwy inicjalizator wuseState.initmożna też wykorzystać do resetowania stanu. - Komponent używa tylko
themez dużegoAppContext, 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.memonie zatrzymuje renderów spowodowanych kontekstem, który czyta komponent. OsobneThemeContextiCartContextograniczają aktualizacje do właściwych konsumentów. Przy bardzo częstych aktualizacjach - store z selektorami.
Zarządzanie stanem · Senior
- 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. - 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
valuerenderuje wszystkich konsumentów. Store'y wykonują selektor każdego subskrybenta i porównują wyniki, więc aktualizacje są punktowe. Biblioteki takie jakuse-context-selectoremulują to na bazie Contextu. - 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. - 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.
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 →