reagent

2023-02-28T17:10:16.585989Z

I’m playing with reagent and have tried implementing a simple tabs component which receives a specification of tabs to render and manages the display of the appropriate pane, as you’d expect. For the most part it works fine; but I’ve now made the tab labels components, and noticed that they’re not reactively re-rendering.

2023-02-28T17:12:22.953309Z

The implementation looks like this:

(defn tab-control [{:keys [id label] :as tab-opts}]
  [:<> [:input (assoc tab-opts
                      :type :radio)]
   [:label {:for id} label]])

(defn tabs [{:keys [name default-tab tabs]} tab-panes]
  (let [selected-tab (r/atom default-tab)]
    (fn [{:keys [name default-tab tabs]} tabs-panes]
      (let [tab-controls (vec (cons :span.tab-controls
                                    (mapv (fn [tab-id]
                                            (let [{:keys [label]} (get tab-panes tab-id)]
                                              [tab-control {:id tab-id
                                                            :name name
                                                            :label label
                                                            :value tab-id
                                                            :checked (= tab-id @selected-tab)
                                                            :on-change #(reset! selected-tab tab-id)}]))
                                          tabs)))
            selected-tab-pane (:pane (get tab-panes @selected-tab))]
        [:div.tabs
         tab-controls
         [:div.tab-pane {}
          selected-tab-pane]]))))
and the example usage is:
(let [{:keys [errors appends deletes corrections]} @state]
  [tabs {:default-tab :errors
         :name :change-type
         :tabs [:errors :appends :deletes :corrections]}
   {:errors {:label [:<> "Errors (" (count errors) ")"]
             :pane [:h1 "Errors"]}
    :appends {:label [:<> "Appends"]
              :pane [:h1 "Appends"]}
    :deletes {:label [:<> "Deletes"]
              :pane [:h1 "Deletes"]}
    :corrections {:label [:<> "Corrections"]
                  :pane [:h1 "Corrections"]}}])
and it’s the (count errors) that I’d expect to be re-rendering

p-himik 2023-02-28T17:13:57.858169Z

In your tabs component, very carefully compare signatures of the outer and inner functions. Also, I would suggest looking into setting up highlighting unused symbols in your editor - very useful, and not only in similar cases.

2023-02-28T17:17:04.419939Z

ahh thanks — code blindness, it’s been a long day! I have unused symbol highlighting already… I was just kinda ignoring it because of the false positives with the outermost symbols being shadowed on the inner function

2023-02-28T17:17:55.838809Z

I was thinking I might replace them with _ but then I’d need to add args-list metadata

p-himik 2023-02-28T17:18:18.149229Z

Ah, to avoid those false positives I use stuff like (fn [{#_#_:keys [name default-tab tabs]} ...] ...).

p-himik 2023-02-28T17:18:38.694319Z

Of course, that doesn't help with in-editor documentation. :(

2023-02-28T17:18:44.998269Z

yeah exactly

p-himik 2023-02-28T17:19:04.142729Z

Oh, wait - it actually does help, at least in Cursive.

2023-02-28T17:19:32.584469Z

I use emacs/cider

p-himik 2023-02-28T17:20:22.456529Z

What about {:keys [_name _default-tab _tabs]}?

2023-02-28T17:21:09.516019Z

lol I actually do that elsewhere… 🙂 I should do that here too! 😩

1
2023-02-28T17:21:18.467689Z

I should probably call it a day 🙂

😄 1
2023-02-28T17:24:05.940609Z

Anyway, thanks for the 🧸ing - it’ll at least mean I can finish for the day without this hanging over me! 🙂

👍 1
🎉 1