ClojuresScript not applying class values with click

42 views Asked by At

I have the following over-engineered code that displays 2 buttons on a page, but when I click on a button nothing happens.

I'm using reagent (r) and mui (m).

(defn settings [id]
  (let [active "active-content-button"
        inactive "content-button"
        classes (r/atom {1 inactive, 2 inactive})]

    (defn toggle-active [button-id]
      (swap! classes assoc 1 inactive)
      (swap! classes assoc 2 inactive)
      (swap! classes assoc button-id active))

    [:div {:style {:padding (* 2 SPACING)}}
     [:div {:class "tab-block"}
      [m/Button {:class (@classes 1) :on-click #(toggle-active 1)} "Filters"]
      [m/Button {:class (@classes 2) :on-click #(toggle-active 2)} "Settings"]]]))

I'm expecting the classes of the buttons to update themselves on click. What am I missing?

2

There are 2 answers

0
Eugene Pakhomov On

A few thinngs:

  • Don't nest defn and/or def. Instead, use let/letfn/fn or move that defn outside
  • Don't use multiple swap!/reset! operations on the same atom. Instead, combine them in a single one
  • You need to use a so-called form-2 component or r/with-let. Without any of those, your r/atom gets re-created on every render of the settings component

Some less important things:

  • Class names can be keywords in Reagent, if you prefer those
  • Mutually exclusive options are better handled with keywords rather than with numbers, i.e. I would remodel your data as active-button (r/atom :filters) and then would choose the class conditionally based on that
0
user2609980 On

The suggestions from the earlier answer would look something like this:

(defn class [active?]
  (if active? "active-content-button" "content-button"))

(defn settings [id]
  (let [active (r/atom :filters)]
    (fn []
      [:div {:style {:padding (* 2 SPACING)}}
       [:div.tab-block
        [m/Button {:class (class (= @active :filters))
                   :on-click #(reset! active :filters)}
         "Filters"]
        [m/Button {:class (class (= @active :settings))
                   :on-click #(reset! active :settings)}
         "Settings"]]])))