crimx/observable-hooks

Defer creation of observable

OliverJAsh opened this issue · 2 comments

As I was migrating from useObservable in rxjs-hooks to the one provided by this library, I ran into an interesting issue. Take this code:

useObservable(() => Rx.of(window.navigator.appName));

This code is part of a component which is rendered on the client and server. Of course, the observable will do nothing on the server, since it will never be subscribed to (effects are never ran in React SSR).

In rxjs-hooks this worked, but when I migrated it to this library I got an error on the server.

ReferenceError: window is not defined

IIUC, in rxjs-hooks the creation of the observable happens during an effect, immediately before subscription: https://github.com/LeetCode-OpenSource/rxjs-hooks/blob/89c4b89265b410a7c46cd5060629637e32c5ce8c/src/use-observable.ts#L37

Whereas in this library, the creation of the observable happens immediately during the render:

const source$Ref = useRefFn(() => init(inputs$Ref.current))

Perhaps we could wrap the init call in defer (from rxjs)? Something like

-  const source$Ref = useRefFn(() => init(inputs$Ref.current))
+  const source$Ref = useRefFn(() => defer(() => init(inputs$Ref.current)))
crimx commented

defer creates a fresh observable for each observer which could be a breaking change for operators like share.

Does this work?

useObservable(() => defer(() => Rx.of(window.navigator.appName)));

Or maybe add more hooks (or another lib) for dealing with server rendering stuff.

Good point, I'll do that for now!