re-frame

Quentin Le Guennec 2024-11-07T12:47:11.641549Z

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 ?

p-himik 2024-11-07T16:22:08.885419Z

Yes, but you should just use reg-sub-raw and not sweat it.

Quentin Le Guennec 2024-11-07T16:26:23.592909Z

I see, thank you

Quentin Le Guennec 2024-11-07T16:46:04.437039Z

what’s the alternative?

p-himik 2024-11-07T16:48:02.638599Z

Something undocumented, not recommended, and never used before in any public code that I've seen. :) Do you really wanna know?

Quentin Le Guennec 2024-11-07T16:48:29.817299Z

Ahah I see. Yes I still wanna know.

p-himik 2024-11-07T16:48:52.218859Z

You can use an impure function as a subscription handler registered with plain reg-sub and deref other subs in there.

Quentin Le Guennec 2024-11-07T16:50:12.690239Z

You mean deref stuff in the computation-fn ?

p-himik 2024-11-07T16:50:55.237769Z

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.

Quentin Le Guennec 2024-11-07T16:51:53.072849Z

I see, thanks. I feel like that’s a piece of re-frame that’s lacking, though.

p-himik 2024-11-07T16:58:43.018059Z

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.

Quentin Le Guennec 2024-11-07T17:04:07.485409Z

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.

Quentin Le Guennec 2024-11-07T17:05:07.175039Z

I’m more of a fulcro person 😄 but at least I agree that it aligns with the philosophy of re-frame

p-himik 2024-11-07T17:07:41.564349Z

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.

p-himik 2024-11-07T17:09:48.288479Z

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.

Quentin Le Guennec 2024-11-07T17:10:57.845719Z

You would need to wrap it in r/reaction tho, wouldn’t you ?

Quentin Le Guennec 2024-11-07T17:11:17.278089Z

(you didn’t misunderstand the issue)

p-himik 2024-11-07T17:13:08.912299Z

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.

Quentin Le Guennec 2024-11-07T17:13:11.854839Z

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] ...))

p-himik 2024-11-07T17:14:23.620579Z

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. ;)

p-himik 2024-11-07T17:22:17.848289Z

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.

Quentin Le Guennec 2024-11-07T17:25:34.341439Z

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.

p-himik 2024-11-07T17:29:15.264729Z

Yeah, and it calls itself that, but I approach it as a library. :)

👍 1