Trzynasta wersja nexta była reklamowana jako rozwiązanie kompletne, w szczególności zacierająca granice między serwerowymi i klienckimi komponentami, umożliwiająca ich dowolne przeplatanie. Sam testowałem ją i opisałem swoje doświadczenia w tym poście z grudnia 2023. Już wtedy zauważyłem, że w konsoli są jakieś nieznane mi warningi, ale nie przejąłem się tym, bo zwykle tego typu ostrzeżenia to drobnostki łatwe i szybkie do naprawienia.
Jednakże, gdy wróciłem do tematu nieco później, w komercyjnym projekcie, to przekonałem się, że tu ostrzeżenia przekazują nam coś istotniejszego, bowiem mówią o użyciu API biblioteki w niewspierany sposób.
Owe ostrzeżenia wyglądają mniej więcej tak:
clientWrapper.tsx:27 Warning: Cannot update a component (`Router`) while rendering a different component (`ClientWrapper`).
To locate the bad setState() call inside `ClientWrapper`,
follow the stack trace as described in https://reactjs.org/link/setstate-in-render
A problem ów pojawia się, gdy próbujemy zawołać komponent serwerowy w komponencie klienckim jak poniżej:
function ClientComponent({ ServerComponent }) {
return (
<>
<Suspense fallback={'loading'}>
<ServerComponent />
// or {ServerComponent()}
</Suspense>
</>
);
}
Dokumentacja wspomina, że wspierane jest:
Passing Server Components to Client Components as Props
Jednakże jest to prawdą jedynie wtedy, gdy serwerowy komponent wołamy na serwerze i przekazujemy rezultat propsem do klienckiego komponentu, jak tu:
function ClientComponent({ serverComponentResult }) {
return (
<>
<Suspense fallback={'loading'}>{serverComponentResult}</Suspense>
</>
);
}
Wydaje się to jedynie drobnym ograniczeniem na pierwszy rzut oka, prawda? Co za różnica?
Ano taka, że co wobec tego z serwerowym komponentem, który zależy propsów z klienta?
Powstał już zresztą na to topic na reddit’cie i większość dyskutujących zdaje się zgadzać, że w tej sytuacji po prostu trzeba wołać API, jak w SPA. Można nawet wołać nextowe akcje, ale to API jest przecież pomyślane do mutowania, więc dla mnie to w pewnym sensie jeszcze gorsze rozwiązanie.
Czuję się więc nieco rozczarowany, bo liczyłem na coś porównywalnego do możliwości Hotwire i LiveView, gdzie w ramach wsparcia słynnego strumieniowania komponentów (component streaming) mógłbym dostać na kliencie wstępnie zrenderowany komponent, zamiast wołać endpoint itd.
Czy nadzieja umarła? Właściwie, to nie jestem pewien. Cofnijmy się na moment. Jak już wspomniałem, jest warning, niemniej jakoś działa.
Co więcej, poświęciłem trochę czasu i udało mi się pozbyć tego ostrzeżenia, jak i rozwiązać pewnie pomniejsze problemy, które napotkałem używając API w niewspierany (rzekomo) sposób.
Można to znaleźć tu. Wiem, że kod jest paskudny (jak to workaround), ale fakt, że działa sprawia, że myślę, czy może jest planowane oficjalne wsparcie dla tej funkcjonalności w przyszłości.
Trzymam za to kciuki, bo jest to dla mnie element poszerzania granic, a więc umożliwiania pisania kodu tak, jak nam to najlepiej pasuje.
Pozdro i do następnego 🖖