Fork me on GitHub
#re-frame
<
2018-09-07
>
b2berry00:09:23

Killer, thanks!

enforser16:09:06

Hey! I was sent here from a recommendation in the clojure discord! Going to copy and paste my problem from there to here:

enforser16:09:23

I'm trying to register a subscription that will be used by multiple components. I was trying to use the on-dispose key (with reg-sub-raw) to dispatch an event when there are no components subscribed - but I've since realized that I actually want to dispatch the event when there is one or less components subscribed. Does anyone know how to go about getting a count of the components which are currently using a subscription?

enforser16:09:46

I think something like this should call :on-dispose when nothing is using it, but in my case I want to run the :on-dispose function when only one thing is using it

(defn sub
  [db [_ id]]
  (reagent.ratom/make-reaction (fn [] (get @db id))
                               :on-dispose #(re-frame/dispatch [:some-event id])))

(re-frame/reg-sub-raw ::sub sub)

mikerod16:09:55

@trailcapital I have no direct answer. I’m wondering if there is a different design angle you could take to not need this though.

mikerod16:09:09

Could you instead track “subscribers” as they are created

mikerod16:09:35

e.g. Perhaps clicking a button is adding this particular component, can’t that click event update the app db with the currently “click/loaded” count

mikerod16:09:06

Similarly, is there some accessible event that may occur when one of these components goes away? e.g. is a “remove click” event happening?

mikerod16:09:18

I have no idea what your constraints are and what these components are, so just some thoughts.

enforser16:09:39

Unfortunately there is no event that specifically occurs when these components disappear. The above chunk of code belongs to something which should hypothetically be used by any component to fetch data. Behind the scenes, the (get @db id) will periodically change because of a go-loop which is polling an external database - updating the app-db if there is no data.

mikerod16:09:11

There are some non-documented (I think) places in re-frame.subs you can look to find the “subscription cache”. Relying on their implementations sounds like not-a-great-idea though for this sort of situation

mikerod16:09:39

> Unfortunately there is no event that specifically occurs when these components disappear. Why is this?

mikerod16:09:53

And does that mean that there is an event that happens when a component appears (the reverse)

mikerod16:09:28

> should hypothetically be used by any component to fetch data. Since it seems questionable as far as a subscription design goes, I don’t know that generalizing on it is a good call.

mikerod16:09:34

I’m being opinionated though.

mikerod16:09:51

and perhaps there are good answers for you. I can’t think of anything that follows the re-frame sort of approach beyond actually capturing your appearance and disappearance of these components more explicitly via the events that occur that causes that to happen. It is really often the case that there is some event that happens that you can hook into that is not about DOM nodes being disposed/React components to be unmounted “mystically” etc.

enforser16:09:30

right, I generally agree that I don't really want to rely on the subscription cache - and perhaps a re-design would be the best solution. The current design has the following: - A 'component' which does not actually display anything in the view - it is just used to source data for multiple other components, by polling the DB. - The other components subscribe to the polled data of the above. - The polling component should always exist behind the scene, so we are manually ensuring that it is being deference, according to re-frame. - Since the polling component always exists, I can't use on-dispose to call the clean up - as the clean up should be triggered by how many other components are subscribed to the polling one.

enforser16:09:24

I'm still trying to wrap my head around this, so there could be some awful design flaw in the way that I'm picturing it!

mikerod16:09:23

So then, > it is just used to source data for multiple other components, by polling the DB where do these come from?

mikerod16:09:31

I guess I sort of see your point

mikerod16:09:54

You have just some unbound size of a component-tree below this “polling-only” component

mikerod16:09:12

So the components are diverse and come from all over the place, no easy to pinpoint events

mikerod16:09:41

A question could be though, do you need this “polling component” at all then

mikerod16:09:27

When this polling-component is created, instead of needing it, why not dispatch a “set-up polling” event

mikerod16:09:40

So now you have 0 components subscribed to it right away. Then perhaps your :on-dispatch setup could work out

mikerod17:09:32

and I’d have to read through it again to check, but if you haven’t, perhaps read through https://github.com/Day8/re-frame/blob/master/docs/Subscribing-To-External-Data.md to see if there is any further inspiration

mikerod17:09:48

That doc focuses on the sub handler itself initiating the setup-event

enforser17:09:00

That link is where I am getting my inspiration!

mikerod17:09:29

I’m on the fence about if I like that approach, it does mention that you could do it a bit different as mentioned, but not an example given with https://github.com/Day8/re-frame/blob/master/docs/Subscribing-To-External-Data.md#the-alternative-approach

mikerod17:09:53

Ok, so from the example above that inspired you, don’t have a top-useless component that never goes away perhaps

mikerod17:09:13

Just have the lower components subscribe to this sub when they need it

mikerod17:09:43

Instead of trying to pass the data down to arbitrarily many components that may or may not need it

mikerod17:09:15

I can somewhat understand why you have it the way you have it, but I think it does cause difficulty in the clean-up side.

mikerod17:09:44

and I’m not sure there are any strong benefits to sticking to it

enforser17:09:37

I think that sounds like it could work. I'll look into this more, and see if that'll work in my use case!

enforser17:09:44

thanks for your help!

mikerod19:09:31

No problem, hopefully something I said was at least somewhat helpful. 😛