re-rxjs / react-rxjs

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

Add getServerSnapshot, fix loop on SSR Subscribe #306

Closed voliva closed 11 months ago

voliva commented 11 months ago

Fixes #305

Something important to keep in mind is that in SSR any children within a Subscribe will not render, because given that components never mount in SSR (including <Subscribe>), it will never get into the stage of rendering the children.

And StateObservable with top-level subscriptions will have their state shared between clients.

codecov[bot] commented 11 months ago

Codecov Report

Merging #306 (54bfb1a) into main (963ff94) will not change coverage. The diff coverage is 100.00%.

@@            Coverage Diff            @@
##              main      #306   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           24        25    +1     
  Lines         1232      1279   +47     
  Branches       141       148    +7     
=========================================
+ Hits          1232      1279   +47     
Files Changed Coverage Δ
packages/core/src/Subscribe.tsx 100.00% <100.00%> (ø)
...ore/src/test-helpers/pipeableStreamToObservable.ts 100.00% <100.00%> (ø)
packages/core/src/useStateObservable.ts 100.00% <100.00%> (ø)

:mega: We’re building smart automated test selection to slash your CI/CD build times. Learn more

CMCDragonkai commented 11 months ago

Does this means one should not use this in server side components?

voliva commented 11 months ago

Does this means one should not use this in server side components?

At the moment I don't really have an answer for this, I haven't played that much with SSR or server-side components.

It's just important to keep in mind that in server-side:

  1. Anything inside <Subscribe> will not render. <Subscribe> is used to subscribe to a source$ before the children are rendered. If <Subscribe> can't subscribe to the source because it never gets mounted, then it will never render its children.
  2. StateObservables with defaultValue will return their default value (just as normal).
  3. Any StateObservables with a subscription somewhere else (e.g. a top-level subscription) will have their state shared between every render. This could be useful, or it could be annoying to get around.

My best advice (again, without having played that much with SSR/NextJS) is to have every StateObservable with a defaultValue on those components that will run on the Server. It gives the most predictable and simple results: They will return the defaultValue while on the server, and execute the subscription when on the client.

Maybe on a future we can leverage something like https://github.com/reactjs/rfcs/pull/229 so that server components also subscribe to the observables, but there are some serious questions regarding cancellation and state sharing.