If I have a subscription that returns a collection of query-vectors, can I register a subscription that subscribes to that collection and then subscribe to each element of the collection, without reg-sub-raw / reaction ?
Yes, but you should just use reg-sub-raw and not sweat it.
I see, thank you
what’s the alternative?
Something undocumented, not recommended, and never used before in any public code that I've seen. :) Do you really wanna know?
Ahah I see. Yes I still wanna know.
You can use an impure function as a subscription handler registered with plain reg-sub and deref other subs in there.
You mean deref stuff in the computation-fn ?
Yes. But don't do it. There's literally 0 reasons not to use reg-sub-raw which was created exactly for the uses cases like yours.
I see, thanks. I feel like that’s a piece of re-frame that’s lacking, though.
Why?.. What's wrong with reg-sub-raw?
From my perspective, it sounds as if someone is asking how to get a nested value from a map and then says that get-in is lacking.
It doesn’t feel much composable, you need to register an extra subscription for something that you might only use once, it would feel more natural to me if you had the option to write multiple input-fn before the computation-fn. Like everything in re-frame, it seems very verbose.
I’m more of a fulcro person 😄 but at least I agree that it aligns with the philosophy of re-frame
It doesn't matter if you need it once or 50 times on every frame - with re-frame, if a view or some other reactive context needs a value from app-db, a subscription has to be used. That's, like, the mechanism to reactively get values from app-db. The fact that a sub has to be registered is of no importance whatsoever.
> it would feel more natural to me if you had the option to write multiple input-fn before the computation-fn
Erm... I'm not sure you're using reg-sub-raw to its full extent then. Either that, or I completely misunderstand what the exact issue is.
You don't have to have any extra interim subs - you can have only that "raw" sub, in addition to the subs that you already have - ones that are used in the vector. You can have 15 derefs in a row, it doesn't matter.
I'll try to approach it with just what you've mentioned in the OP:
(rf/reg-sub-raw :all-the-subs
(fn [_ _]
(let [ids @(rf/subscribe [:the-sub-that-returns-a-vector-of-sub-ids])]
;; Gotta use `mapv` to make sure that everything is `deref`ed.
(mapv (fn [id] @(rf/subscribe id)) ids))))
That's it, there are no additional subs.You would need to wrap it in r/reaction tho, wouldn’t you ?
(you didn’t misunderstand the issue)
Ah, right, sorry - I have my own version of reg-sub-raw that does that for me, because I've never used reg-sub-raw without everything being wrapped in a reaction. Although I do appreciate such a possibility - that allows you to return (rf/subscribe ...) directly from the handler, for example. I think I use that somewhere, I just named my own wrapper for reg-sub-raw in a different way, to make that more clear.
So yeah, you gotta wrap the body of the function in r/reaction - but that still doesn't necessitate an extra subscription.
From your example, this is what I meant:
(rf/reg-sub :all-the-subs
(fn [] (rf/subscribe [:the-sub-that-returns-a-vector-of-sub-ids]))
(fn [sub-vector] (mapv rf/subscribe sub-vector))
(fn [ids] ...))But that's less direct, and just as many logical parts, so it doesn't make anything simpler really.
You can, however, write your own version of reg-sub that does that - it's very, very trivial. It would just expand to reg-sub-raw. Saving you nothing but requiring you to create extra functions. ;)
Just in case it might be helpful with some other things.
My own relatively thin wrappers around re-frame's stuff that I find very helpful or just convenient:
• (<sub ...) and #(>evt ...) as aliases to @(rf/subscribe ...) and #(rf/dispatch ...)
• A version of reg-sub that accepts a vector path as an "argument" for the :-> sugar
• All version of reg-evt-* always apply trim-v and an interceptor that validates app-db across a spec and rolls back with an extra error event dispatched if the value is bad
• Probably other things that I don't have at the top of my head
You can also chain sugar like this (which I'll probably simplify even further so there are no repetitions):
(rf/reg-sub ::-dialog :-> [:dialogs dlg-id])
(rf/reg-sub ::in-progress? :<- [::-dialog] :-> :in-progress?)
(rf/reg-sub ::done? :<- [::-dialog] :-> :done?)
There are many small things like this. And for better or worse, they aren't a part of re-frame so everyone ends up with something they've created on their own.I see, thanks a lot for your insight. Unfortunately I don’t think I can really use those in my current team. I agree that although re-frame is tiny, it’s very extendable. The issue is that people use it as a framework.
Yeah, and it calls itself that, but I approach it as a library. :)