re-rxjs / react-rxjs

React bindings for RxJS
https://react-rxjs.org
MIT License
555 stars 20 forks source link

SSR and react-rxjs #313

Open Jesus-Gonzalez opened 1 year ago

Jesus-Gonzalez commented 1 year ago

Hello,

For now, the applications I've been working on with react-rxjs are SPA that are client side rendering only - no SSR is implemented. Given the new trend on frontend application development with javascript - SSR is becoming the norm for every project. I've also started working on a side-project that's going to implement SSR - although it's initially rendering client side only.

Are there any guide or best practices in order to implement SSR and using react-rxjs?

I'm thinking about possible issues arising - for example:

Jesús

voliva commented 1 year ago

This library was primarily designed for client-side-only SPAs, so its support for SSR is minimal. The components will render normally in SSR, but the app won't subscribe to any of the observables.

I have prepared a very small NextJS sandbox to demonstrate that it renders on server by using the default value, and for states without a default value it works fine with suspense as well: https://codesandbox.io/p/devbox/holy-framework-qplc5c?file=%2Fapp%2FCounter.tsx%3A30%2C2. To check it's actually being rendered in the server, you can access the result sandbox result directly on the URL https://qplc5c-3000.csb.app/ and look at the network tab. Keep in mind the SSR doesn't ever subscribe to any of the observables, it just gets the initial value or renders components as Suspended.

The primary reason for this limitation is that effects do not execute in SSR. You could externally manage the subscription of observables, and the components that use them will get their current value, but it's importat to note that the observables are shared for all the clients making requests. Which it's very limited in terms of what logic you can represent and use within the server.

On the last patch we did for SSR #306, I commented a few implications and some recommendations for this. But in a nutshell, avoid using top-level subscriptions, specify default values whenever possible, and keep in mind that anything inside a <Subscribe> will only be rendered in the client: This is because <Subscribe> only renders its children after it has subscribed to the source$, but it won't subscribe to the source$ when running in the server because effects don't run there.

Also I just checked and react-rxjs doesn't work at all with Server Components. I'm thinking this is expected, considering that hooks cannot even be used in Server Components, so there shouldn't be any need to import anything from react-rxjs. You can import from @rx-state/core which has the state primitive without React's bindings (hooks + context + etc.) for building observables, but you still have to keep in mind any state those observables have will be shared among all clients performing requests, because they are defined in the global scope.

In summary, don't rely on react-rxjs to perform any observable logic when running on the server.