英文:
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
defn
and/ordef
. Instead, uselet
/letfn
/fn
or move thatdefn
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, yourr/atom
gets re-created on every render of thesettings
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
答案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"]]])))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论