re-rxjs / react-rxjs

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

When is <Subscribe /> actually necessary? #171

Closed hoclun-rigsep closed 3 years ago

hoclun-rigsep commented 3 years ago

Gentlemen,

I really like what you are doing here. However I am having trouble with this part of the documentation:

Something to note is that a subscription on the underlying observable must be present before the hook is executed. We can use Subscribe to help us with it:

    function CharacterCounter() {
      return (
        <div>
          <Subscribe source$={charCount$}>
            <TextInput />
            <CharacterCount />
          </Subscribe>
        </div>
      )
    }

When I remove the Subscribe component, nothing bad seems to happen. I've spent a while reading your delightfully succinct code but thought it would be easier to ask for an example where Subscribe is clearly necessary than try to work one out for myself. Thanks in advance.

josepot commented 3 years ago

When I remove the Subscribe component, nothing bad seems to happen.

That's because you must be using an old version of the library, or because you have subscribed from somewhere else. Because this is what happens with the current version if the a subscription on the underlying observable is not present when the hook is evaluated on render.

In previous versions of this library we were trying to make the hooks work without the need of using Subscribe. In other words: we allowed for the initial subscription to happen on render, but then we realized that it was too hacky and full of edge cases that we didn't want to deal with.

Also, we realized that wasn't the kind of mental models that we wanted to promote, because ideally the subscriptions that trigger io side-effects (fetch, websocket connections, etc) should always happen before render, while there are lots of subscriptions that can (and should) take place after the component is mounted. So, eventually we gave up on trying to support that madness, and we decided to promote other patterns, instead. Like using Subscribe.

That being said, Subscribe is not always necessary. Subscribe is just a super-set of Suspense with the fallback parameter defaulted to null. All what it does is to use Suspense and subscribe to the source after mount. However, if you don't want to leverage Suspense, then bind accepts a second optional parameter that's the default value that can be used when there is no subscription (or when there is a subscription, but no value has been emitted yet), if you use that overload of bind, then you don't need to use Subscribe because in that case the hook returned from bind will never trigger "Suspense".

Also, there are instances when what you want is a top level subscription (so that the requests happen ASAP) combined with Suspense, for instance.

Anyways, sorry if I gave you too much information. I just wanted to make sure that you understand the "magic" behind "Subscribe" :sweat_smile:

We need to improve the docs and we need to find ways to explain these things better. So, if you wan to help us with that, we are very open to suggestions :slightly_smiling_face:.

hoclun-rigsep commented 3 years ago

Thank you for your thorough response, @josepot. I'm planning to rely heavily on this library in a staffing application I am developing at FDNY and want to get to know it well before I begin. For now I can confirm that I was running an old version. I think I installed it with npm install react-rxjs: would that explain it?

josepot commented 3 years ago

I'm planning to rely heavily on this library in a staffing application I am developing at FDNY and want to get to know it well before I begin

Nice! Thanks for letting me know that! We are heavily relying on this library on many different projects at Adaptive (the company that I work for) and so far it's working out really well for us. Although, I have to find ways to make sure that we are able to spread the knowledge and the mental-models that we want to promote beyond our company. That's why -among other initiatives- we are working on a re-architected version of ReactiveTrader.com, if you are interested, the code of this re-architected version can be found here. We still have to add READMEs and document things properly, but maybe it could be useful for you to pay attention at the things that we are doing in there. Also, please feel free to raise any issues/questions/comments if you need help with something.

I can confirm that I was running an old version. I think I installed it with npm install react-rxjs: would that explain it?

yes! my bad! I just added a deprecation message to it. So, at least now if someone else installs it, then they will get a warning asking them to install @react-rxjs/core instead.

hoclun-rigsep commented 3 years ago

I'd love to help out and I would be happy to read any WIP mental-model documents or threads you have.

josepot commented 3 years ago

Hi @hoclun-rigsep ,

I'm very sorry that it took me this long to get back at you. If you are still interested, we would love to get some help and feedback from you, please send me a DM on twitter if you are still up for the challenge :pray:, because we could defenitelly use some help :slightly_smiling_face:. We are about to release v1 and we want to completely re-write the docs. Also, if you would like to know more about the mental models that we want to promote with this library, I think that you could find this presentation helpful.

Also, we have improved the way that Subscribe works and it's a lot more ergonomic now.

Once again, I'm very sorry for the late response :bow:

hoclun-rigsep commented 3 years ago

Hi @josepot,

I am sorry but I do not use Twitter. I also seldom view recorded talks, but I watched your whole presentation and wish to tell you that I found it extremely effective in establishing the justification for React-RxJS. For a couple of years I've been working on an Angular application, and the more I learned about RxJS, the more I used it to manage state. In Angular there's perhaps less need for a binding such as yours because you can just subscribe in the component. But the way components can be expected to update, the opacity or verbosity of other things in Angular, et cetera, make me think that if I could do it over again I think I'd go with React and React-RxJS.

I have a useless comment to make: the way you compared the component tree with the state graph was brilliant, but for some reason I didn't get the same value out of the diagram at https://react-rxjs.org/docs/tutorial/github-issues#identifying-the-state-of-the-app. If I can put my finger on exactly why, I'll let you know. :)

I am an able writer and I am willing to help with documentation. However, I'm not sure you would want someone who hasn't written an application that manages state this way, and the project at work that I had in mind is "on hold"—probably forever. (It's a long story.)

Anyway, if you wish to reach me other than via this thread, my email address is james.amberger@fdny.nyc.gov and if you want my PGP key let me know. I'm also still subscribed to this thread so that works too.

CMCDragonkai commented 1 year ago

I stumbled on this issue searching for how to use <Suspense> with react-rxjs. It appears that it doesn't work like:

<Suspense fallback={<p>Loading</p>>
  <ThingThatUsesHook />
</Suspense>

That was a bit confusing because the docs https://react-rxjs.org/docs/core-concepts#suspense doesn't appear to say that you're not supposed to do this and instead Subscribe is what you want.

<Subscribe>
  <ThingThatUsesHook />
</Subscribe>

Question though, if I have a list like:

{
  todoIds.map((id) => (
    <ThingThatUsesHook key={id} id={id} />
  ))
}

What's the best place to put the <Subscribe>? Inside the the map, or surrounding the map?