Can't wrap in reagent

I want to wrap a reagent vector that includes a re-com checkbox, where the checkbox does not directly rely on a subscription, but a value that is calculated (in the component) from that subscription. I’ve boiled the problem down to the following code.

(rf/reg-sub
  ::get-value
  (fn [db _]
    (::value db)))

(rf/reg-event-fx
  ::set-value
  (fn [{:keys [db]} [_ value]]
    {:db (assoc db ::value value)}))

(defn wrapper
  [body]
  (fn [body] ;; adding `body`here fixed the problem. Thanks @p-himik
    [:div body]))

(defn test
  []
  (let [sub (rf/subscribe [::get-value])]
    (fn []
      [:div
       [wrapper
        (let [selected? @sub]
          [rc/checkbox
           :model selected?
           :on-change #(rf/dispatch [::set-value %])
           :label "Wrapped - :model is computed - doesn't work"])]
       [wrapper
        [rc/checkbox
         :model sub
         :on-change #(rf/dispatch [::set-value %])
         :label "Wrapped - :model is subscription - works"]]
       (let [selected? @sub]
         [rc/checkbox
          :model selected?
          :on-change #(rf/dispatch [::set-value %])
          :label "Not wrapped - :model is computed - works"])])))

I render [test] and when I click the first checkbox, the value changes but the checkbox does not change state. So for some reason reagent doesn’t re-render it.

The two other checkboxes demonstrate that it is the combination of wrapping the checkbox and setting the :model for the checkbox to a computed value instead of sub that causes the problem. The reason why I am computing the value instead of using sub directly is that I am in reality rendering lots of dynamically created checkboxes (within the same wrapper) and I don’t want to create a subscription for each one of them, instead they dereference the subscription and check if their specific key is true or false.

Any idea on how I can get this to work?

You’re hitting what this page describes as “rookie mistake”: reagent/ComponentNotRerendering.md at c214466bbcf099eafdfe28ff7cb91f99670a8433 · reagent-project/reagent · GitHub

Specifically, this part:

If the props to a Component change, but it doesn’t appear to re-render, then the cause will be this rookie mistake: you forgot to repeat the parameters in the inner, anonymous render function.

2 Likes

Yes! Rookie for sure - thank you! I’ve updated the code.