Problem z subskrypcjami zewnętrznego store’a
Proszę poznać zjawisko tearingu oraz przyczyny, dla których subskrypcje zewnętrznych store’ów za pomocą useState lub useRef są niebezpieczne we współbieżnym React.
Problem z subskrypcjami zewnętrznego store’a to bezpłatna lekcja React Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej React Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs React Academy zawiera 4 lekcji w sumie.
Czym jest zewnętrzny store
Zewnętrzny store to dowolne źródło stanu znajdujące się poza drzewem React, na przykład store Redux, przeglądarkowe API takie jak matchMedia lub zwykły obiekt na poziomie modułu z własnym mechanizmem subskrypcji.
React nie zarządza tym stanem, dlatego musi subskrybować zmiany i odczytywać migawki, aby utrzymywać komponenty w synchronizacji z aktualną zawartością store.
Naiwna subskrypcja z użyciem useState + useEffect
Typowe podejście polega na wczytaniu wartości store do useState, a następnie użyciu useEffect do zasubskrybowania zmian i wywołania setState za każdym razem, gdy store się zmieni. Na pierwszy rzut oka wydaje się, że komponent pozostaje dzięki temu aktualny.
Rozwiązanie działa przy prostym, synchronicznym renderowaniu, ale ma subtelną wadę, która staje się widoczna, gdy React renderuje współbieżnie i może wstrzymywać lub rozpoczynać pracę ponownie w jej trakcie.
Problem tearingu
Tearing występuje, gdy różne części interfejsu wyświetlają różne wartości tego samego store podczas jednego przebiegu renderowania. Renderowanie współbieżne może przerwać i wznowić pracę, a w międzyczasie store może się zmienić.
Wynikiem jest niespójny ekran, na którym jeden komponent pokazuje starą wartość, a drugi nową — niespójność, która przed wprowadzeniem funkcji współbieżnych była w praktyce niemożliwa.
Przykład: tearing przy zmianie trybu ciemnego w trakcie renderowania
Wyobraźmy sobie wiele komponentów odczytujących store motywu podczas współbieżnego renderowania React. Jeśli użytkownik włączy tryb ciemny w połowie tego procesu, komponenty wyrenderowane przed zmianą pokażą jasny motyw, a te wyrenderowane po niej — ciemny.
Przez jedną klatkę ekran będzie częściowo jasny, a częściowo ciemny, ponieważ wartość store zmieniła się w trakcie renderowania, którego React nie potraktował atomowo.
Dlaczego useEffect jest zbyt późny
Efekty są uruchamiane po zatwierdzeniu renderowania, dlatego subskrypcja oparta na useEffect nie może zagwarantować, że wartość odczytana podczas renderowania będzie zgodna ze store w chwili zatwierdzenia. Subskrypcja uruchamia się zbyt późno, aby zapobiec niespójnemu wyświetleniu.
Zanim efekt ponownie ustanowi subskrypcję i zaktualizuje stan, niespójna klatka może już zostać pokazana użytkownikowi.
Przestarzałe useMutableSource
Wcześniejsze eksperymentalne API o nazwie useMutableSource miało rozwiązać problem bezpiecznego odczytu zewnętrznego stanu podczas renderowania współbieżnego, ale jego API okazało się trudne do poprawnego użycia i nigdy nie zostało wydane jako stabilne.
Zespół React zastąpił je prostszym i wygodniejszym prymitywem, który zapewnia te same gwarancje spójności bez związanych z nim pułapek.
useSyncExternalStore jako rozwiązanie
useSyncExternalStore to oficjalny hook służący do subskrybowania zewnętrznych store w sposób bezpieczny dla renderowania współbieżnego. Koordynuje on działanie z React, dzięki czemu odczyty pozostają spójne w całym renderowaniu i nie dochodzi do tearingu komponentów.
Stał się zalecanym prymitywem dla autorów bibliotek, którzy potrzebują niezawodnie łączyć zewnętrzny stan z React podczas renderowania współbieżnego.
Które biblioteki zostały dotknięte zmianą
Dotyczyło to bezpośrednio bibliotek stanu, które subskrybują zewnętrzne store, w tym Redux, MobX i Valtio. Każda z nich musiała przyjąć nowy prymityw, aby zachować bezpieczeństwo po wprowadzeniu funkcji współbieżnych.
Właśnie dlatego ich integracje z React zostały zaktualizowane tak, aby wewnętrznie wywoływać useSyncExternalStore zamiast polegać na starszym wzorcu useState z useEffect.
Spójny snapshot i bezpieczeństwo współbieżności
Hook gwarantuje, że każdy komponent odczytujący store podczas renderowania widzi ten sam snapshot, a także wymusza synchroniczne ponowne renderowanie, jeśli store zmieni się w sposób, który w przeciwnym razie doprowadziłby do tearingu.
To połączenie spójnego snapshotu i bezpieczeństwa współbieżności stanowi główną przewagę tego hooka nad ręcznie implementowanymi subskrypcjami.
Prymityw przygotowany na przyszłość
Korzystając z useSyncExternalStore, zachowują Państwo poprawność subskrypcji w miarę rozwoju modelu renderowania Reacta. Korzystają Państwo z gwarancji zapewnianych przez framework zamiast niedoskonale implementować je samodzielnie.
Dzięki temu jest to trwały i zalecany sposób podłączania dowolnego zewnętrznego źródła prawdy do komponentów Reacta.
Szybkie sprawdzenie: problem tearingu
Proszę potwierdzić, co oznacza tearing we współbieżnym renderowaniu.
Podsumowanie: problemy z subskrypcją zewnętrznego store'a
Zewnętrzne store'y działają poza Reactem, a naiwna subskrypcja oparta na useState i useEffect nie może zapobiec tearingowi, gdy renderowanie jest współbieżne. Efekty uruchamiają się zbyt późno, aby zapewnić spójność odczytów w ramach jednego renderowania.
useSyncExternalStore zastępuje porzucony useMutableSource i zapewnia spójny snapshot oraz bezpieczeństwo współbieżności. Biblioteki takie jak Redux, MobX i Valtio przyjęły go jako prymityw przygotowany na przyszłość do obsługi subskrypcji store'ów.
Często zadawane pytania
Czy lekcja „Problem z subskrypcjami zewnętrznego store’a” jest bezpłatna?
Tak — pełny tekst „Problem z subskrypcjami zewnętrznego store’a” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu React Academy, przejdź na CoddyKit PRO. Kurs React Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Problem z subskrypcjami zewnętrznego store’a”?
Proszę poznać zjawisko tearingu oraz przyczyny, dla których subskrypcje zewnętrznych store’ów za pomocą useState lub useRef są niebezpieczne we współbieżnym React. Ćwiczysz React Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć React Academy?
Nie wymagamy żadnego doświadczenia. React Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Problem z subskrypcjami zewnętrznego store’a”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji React Academy?
Tak. Każda lekcja React Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Problem z subskrypcjami zewnętrznego store’a
- API useSyncExternalStore i parametry
- Subskrybowanie API przeglądarki
- Budowanie niestandardowego store’a za pomocą useSyncExternalStore