SolidJS 2.0 wprowadza natywny model danych asynchronicznych, który pozwala komponentowi traktować obietnicę (promise) jak każdą inną wartość reaktywną, i robi to bez kaskady ponownych renderowań, które programiści React obserwują przy użyciu Suspense i hooków. Zmiana ta jest istotna, ponieważ pozwala zachować interfejs użytkownika (UI) na ekranie podczas odświeżania danych, redukuje ilość kodu boilerplate i oferuje konkretną ścieżkę dla zespołów React do przeniesienia kodu pobierania danych do Solid.
Dlaczego model asynchroniczny Solid działa inaczej
W React komponent potrzebujący danych zazwyczaj wywołuje hook (często niestandardowy), który zwraca obiekt przypominający obietnicę (promise), a następnie opakowuje UI w <Suspense>, aby wyświetlić fallback podczas rozstrzygania obietnicy. Za każdym razem, gdy obietnica zostaje rozstrzygnięta, React planuje ponowne renderowanie; jeśli ten sam komponent później ponownie pobiera dane, fallback może na chwilę pojawić się nad treścią, która jest już widoczna.
Solid odwraca ten schemat. Obietnica (promise) jest po prostu wartością, którą śledzi graf reaktywności. Gdy obliczenie odczytuje tę wartość, graf wstrzymuje ten odczyt do momentu rozstrzygnięcia obietnicy, ale reszta interfejsu pozostaje wyrenderowana. Przy pierwszym montażu komponentu granica <Loading> może wyświetlić fallback; po tym czasie ponowne pobranie danych pozostawia istniejący DOM nietkniętym, dopóki nie dotrą nowe dane. Brak jawnego „await” wewnątrz komponentu, brak createResource, brak ręcznego przełączania stanów.
Podstawowe prymitywy
- Granica
<Loading>– Zastępuje Reactowe<Suspense>. Wyświetla fallback tylko podczas początkowego ładowania. Po pierwszym renderowaniu (paint) oczekujący odczyt nie zastępuje interfejsu; stara treść pozostaje widoczna do momentu rozstrzygnięcia nowej wartości. Można przekazać właściwośćon, aby wymusić wyświetlenie spinnera przy konkretnym ponownym pobieraniu danych. - Komponent
<Reveal>– Kontroluje, jak wiele granic<Loading>pojawia się razem. Możliwości wyboru:- Sekwencyjnie: granice pojawiają się jedna po drugiej zgodnie z kolejnością w DOM.
- Razem: wszystkie pojawiają się jednocześnie, gdy wszystkie dane są gotowe.
- Naturalnie: każda pojawia się, gdy tylko jej własne dane zostaną odebrane.
- Sygnał
isPending– Zwracatrue, gdy dany odczyt jest w toku. Można go użyć do nałożenia cienkiego paska ładowania lub subtelnej animacji, podczas gdy główna treść pozostaje widoczna, co zapewnia darmową strategię „stale-while-revalidate”. - Generator
action– Zastępuje aktualizacje stanu mutowalnego w React.action(function*…)może optymistycznie aktualizować interfejs, użyćyield, aby poczekać na odpowiedź serwera, a następnie uzgodnić (reconcile) wynik po rozstrzygnięciu obietnicy. Interfejs wydaje się błyskawiczny, a krok uzgadniania jest wbudowany w prymityw.
Jak poszczególne elementy mapują się na koncepcje Reacta
| Cecha | Podejście React | Podejście Solid 2.0 |
|---|---|---|
| Pobieranie danych | use() (eksperymentalne) lub hooki firm trzecich; wynik opakowany w <Suspense> |
createMemo (lub podobne), które zwraca obietnicę; odczyt bezpośrednio w JSX |
| UI ładowania | <Suspense> może ponownie wywoływać fallback przy każdym ponownym pobieraniu danych |
<Loading> tylko przy pierwszym ładowaniu; ponowne pobieranie zachowuje stary interfejs |
| Odświeżanie | useTransition w celu odroczenia aktualizacji UI |
isPending sygnalizuje oczekujące odczyty bez zmiany interfejsu |
| Mutacje | useState/useReducer + wywołania asynchroniczne, często opakowane w niestandardowe akcje |
action(function*…) z wbudowaną obsługą optymistyczną |
Praktycznym efektem jest to, że Solid wbudowuje to, co React traktuje jako oddzielne hooki, bezpośrednio w rdzeń silnika reaktywności.
Przewodnik migracji krok po kroku
- Zidentyfikuj źródło danych – W React prawdopodobnie masz
const data = useMyFetch(url). W Solid zastąp to memo, które zwraca obietnicę:const data = createMemo(() => fetch(url).then(r => r.json())). - Owiń komponent najwyższego poziomu – Jeśli komponent renderuje się przed rozwiązaniem obietnicy, otocz go
<Loading fallback={<Spinner/>}>…</Loading>. Fallback pojawia się tylko przy pierwszym montowaniu. - Zastąp spinnery przy każdym ponownym pobieraniu danych – Tam, gdzie wcześniej przełączałeś flagę ładowania, teraz odczytaj
isPending(data). Użyj tej wartości boolean, aby wyrenderować subtelny wskaźnik, podczas gdy istniejący interfejs użytkownika pozostaje na ekranie. - Konwertuj aktualizacje optymistyczne – Jeśli używałeś
setState(prev => ({...prev, optimisticValue})), a następnie wywołania asynchronicznego, przepisz to jakoconst update = action(function* (newValue) { state = newValue; const server = yield fetch(...); state = reconcile(server); });. Generator oddaje kontrolę do czasu odpowiedzi serwera, a następnie automatycznie aktualizuje graf reaktywny. - Obsługuj wiele elementów asynchronicznych – Zagnieżdżaj granice
<Loading>w zależności od potrzeb, a następnie dodaj wrapper<Reveal>, aby zdecydować, czy mają pojawić się razem, czy jeden po drugim. Zastępuje to wzorce, w których programiści React rozdzielali wiele komponentów<Suspense>za pomocą złożonych kontroli stanu. - Przetestuj przepływ – Ponieważ Solid nie wykonuje ponownego renderowania po rozwiązaniu obietnicy, sprawdź, czy aktualizacje UI nadal zachodzą tam, gdzie tego oczekujesz. Graf reaktywny automatycznie propaguje zmiany; nie ma potrzeby stosowania dodatkowych wywołań
useEffect.
Co wciąż jest w fazie zmian
Async API w Solid 2.0 jest obecnie w wersji beta. Nazwy takie jak <Loading> i action mogą ulec zmianie przed stabilnym wydaniem, a dokumentacja wciąż ewoluuje. Główna idea — traktowanie obietnic jako wartości reaktywnych — pozostaje niezmieniona, ale wczesni użytkownicy powinni spodziewać się drobnych zmian naruszających kompatybilność, gdy biblioteka będzie się stabilizować.
Kto na tym zyska
- Zespoły React pracujące z intensywnym pobieraniem danych – Zmniejszona potrzeba korzystania z zewnętrznych bibliotek stanu oraz wbudowany wzorzec stale-while-revalidate mogą zmniejszyć rozmiar paczki i uprościć bazy kodu.
- Aplikacje skoncentrowane na wydajności – Unikając pełnego ponownego renderowania komponentów przy każdym pobieraniu danych, Solid zapewnia płynniejsze aktualizacje wizualne, szczególnie na urządzeniach o słabszych parametrach.
- Programiści zmęczeni „mignięciem spinnera” – Zachowanie granicy
<Loading>typu „tylko przy pierwszym ładowaniu” eliminuje powszechną irytację spowodowaną mignięciem spinnera na treści, która jest już widoczna.
Możliwe wady
- Status beta – Dopóki API się nie ustabilizuje, projekty długoterminowe mogą wymagać uwzględnienia w budżecie późniejszych prac związanych z migracją.
Na co zwrócić uwagę w następnej kolejności
Śledź oficjalny changelog pod kątem ewentualnych zmian nazw <Loading> lub action.
Podsumowując: SolidJS 2.0 pozwala traktować obietnice jako wartości reaktywne pierwszoklasowe, utrzymując stabilny interfejs użytkownika podczas odświeżania danych i eliminując potrzebę stosowania zestawu hooków w stylu React. Dla zespołów gotowych wyjść poza model skoncentrowany na ponownym renderowaniu, ścieżka migracji jest jasna, korzyści wydajnościowe są namacalne, a jedynym realnym ryzykiem jest typowa dla fazy beta niepewność.
