Fork me on GitHub
#re-frame
<
2021-07-16
>
jthibaudeau17:07:51

Hi, I have some questions about subscriptions. First question, is it acceptable to deref subscriptions within other subscription handlers? We thought this might not be a good idea and then we implemented the following pattern for a subscription that had some complicated dependencies. We have ::test-sub that needs the value produced by ::signal-sub to produce it's value. We then have ::test-complex-sub that takes an argument at subscribe time which is used in the signal function to subscribe to ::signal-sub. That sub is then passed to subscribe as the signal for ::test-sub to get the value ::test-complex-sub needs to do it's work. (Sorry if the description is hard to follow, the code is below)

(re-frame/reg-sub ::test-sub
                  (fn [db _ [signal-value]]
                    (do-something db signal-value)))

(re-frame/reg-sub ::signal-sub
                  (fn [db [_ arg1]]
                    (produce-signal-value db arg1)))

(re-frame/reg-sub ::test-complex-sub
                  (fn test-complex-sub-signal-fn [[_ arg1]]
                    (let [signal-sub (re-frame/subscribe [::signal-sub arg1])]
                      (re-frame/subscribe [::test-sub] [signal-sub])))
                  (fn complex-handler [data]
                    (do-stuff data)))

(defn component [arg1]
  (let [test-complex-sub (re-frame/subscribe [::test-complex-sub arg1])]
    (fn []
      [:div @test-complex-sub])))
This pattern makes use of the ability of re-frame/subscribe to take the dynv argument. But we saw in the docstring that :
`dynv` is an optional 3rd argument, which is a vector of further input signals (atoms, reactions, etc), NOT values. This argument exists for historical reasons and is borderline deprecated these days.
It seems to be working fine, we are just a bit worried about the deprecation warning. Is there an alternative way that doesn't make use dynv to accomplish the same thing? (If we can deref subscriptions within other subscriptions with no problems then we can probably just do that)

p-himik17:07:22

> is it acceptable to deref subscriptions within other subscription handlers? Yes, but note that the main sub will be recomputed on each app-db change, even if you don't use it. If you don't like it, use reg-sub-raw instead. Another alternative is to not use a sub for that at all. Instead, just extract it into a function that should be called only from within view functions. Something like this:

(defn get-y [v]
  (let [x @(subscribe [:x v])]
    @(subscribe [:y x])))

jthibaudeau17:07:10

Cool, thank you! That should make things more straight forward. Does that also mean something like this is fine, provided ::signal-sub doesn't need to take any values?

(re-frame/reg-sub
  ::test-sub
  :<- [::signal-sub]
  (fn [signal [_ arg]]
    @(re-frame/subscribe [::other-sub signal arg])))

p-himik17:07:44

Yes, should be perfectly fine.