英文:
ClojuresScript not applying class values with click
问题
我有以下过度工程的代码,在页面上显示两个按钮,但当我点击按钮时什么都不发生。
我正在使用reagent (r) 和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 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?
答案1
得分: 2
一些要点:
- 不要嵌套 
defn和/或def。取而代之,使用let/letfn/fn或将defn移到外部。 - 不要在相同的原子上使用多个 
swap!/reset!操作。取而代之,将它们合并为一个单独的操作。 - 你需要使用所谓的 form-2 组件 或 
r/with-let。如果没有这些,你的r/atom会在每次渲染settings组件时重新创建。 
一些次要的事项:
- 在Reagent中,类名可以是关键字,如果你更喜欢的话。
 - 互斥的选项最好使用关键字而不是数字来处理,例如,我会将你的数据重新建模为 
active-button (r/atom :filters),然后基于它有条件地选择类。 
英文:
A few thinngs:
- Don't nest 
defnand/ordef. Instead, uselet/letfn/fnor move thatdefnoutside - 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, yourr/atomgets re-created on every render of thesettingscomponent 
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 
答案2
得分: 0
以下是翻译好的部分:
(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"]]]))
英文:
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"]]])))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论