This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-01-24
Channels
- # announcements (22)
- # babashka (33)
- # babashka-sci-dev (161)
- # beginners (25)
- # calva (57)
- # cider (6)
- # clara (6)
- # clerk (14)
- # clj-kondo (24)
- # clojars (10)
- # clojure (65)
- # clojure-austin (1)
- # clojure-conj (2)
- # clojure-europe (23)
- # clojure-miami (3)
- # clojure-nl (3)
- # clojure-norway (3)
- # clojure-uk (3)
- # clojurescript (28)
- # cursive (24)
- # datomic (136)
- # emacs (38)
- # graalvm (29)
- # graphql (3)
- # introduce-yourself (8)
- # jackdaw (4)
- # jobs-discuss (9)
- # malli (5)
- # nbb (36)
- # off-topic (11)
- # pathom (58)
- # polylith (2)
- # practicalli (1)
- # re-frame (5)
- # reagent (11)
- # releases (1)
- # remote-jobs (8)
- # sci (15)
- # shadow-cljs (31)
- # slack-help (2)
- # spacemacs (11)
- # sql (7)
- # tools-build (9)
Hi,
I am having a problem getting test-wrapper
from the function below to change when clicking another one of the buttons in test-property-input
after clicking another one first. The counter
atom should be recreated for each type
argument test-wrapper
is called with.
Any help greatly appreciated.
Edit: Not sure how clear my explanation is, so here is another attempt: When clicking 'Add A' it returns 'It's X with counter 0!' as expected but when clicking 'Add C' afterwards it doesn't change to 'It's Y with counter 0!' as I would expect it to but instead simply stays the same.
Edit2: So it does work if I first set adding?
to false
which I would guess unmounts test-wrapper
and recreates it when clicking one of the buttons again. Any way to force unmount it when clicking any of the buttons?
(defn test-wrapper [type _m]
(let [counter (r/atom 0)]
(fn [_ _]
[:<>
(condp = type
:x [:p "It's X with count " @counter "!"]
:y [:p "It's Y with count " @counter "!"]
[:p "Unknown type: " type])
[:button.button {:on-click #(swap! counter inc)} "Inc"]])))
(defn test-property-input []
(let [is-adding? (r/atom false)
adding-type (r/atom :a)]
(fn []
[:<>
[:div.buttons
[:button.button
{:class (when (= @adding-type :a) "is-primary")
:on-click (fn [_]
(reset! adding-type :a)
(reset! is-adding? true))}
"Add A"]
[:button.button
{:class (when (= @adding-type :b) "is-primary")
:on-click (fn [_]
(reset! adding-type :b)
(reset! is-adding? true))}
"Add B"]
[:button.button
{:class (when (= @adding-type :c) "is-primary")
:on-click (fn [_]
(reset! adding-type :c)
(reset! is-adding? true))}
"Add C"]]
(when @is-adding?
(let [[t m] (condp = @adding-type
:a [:x {}]
:b [:x {}]
:c [:y {}]
[nil {}])]
[test-wrapper t m]))])))
Got it working with an additional layer of indirection. Not really fond of this solution but if it works...
(defn x-wrapper [m]
(test-wrapper :x m))
(defn y-wrapper [m]
(test-wrapper :y m))
(defn test-property-input []
(let [is-adding? (r/atom false)
adding-type (r/atom :none)]
(fn []
[:<>
,,,,
(when @is-adding?
(condp = @adding-type
:a [x-wrapper {:key 1}]
:b [x-wrapper {:key 2}]
:c [y-wrapper {:key 3}]
nil))])))
Your first version makes the "Rookie mistake" described in this section: https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md#form-2--a-function-returning-a-function
But when I pass type and m to the inner function it reuses the counter atom which I do not want. I want each call to test-wrapper with a certain type as parameter to have its own counter and not reuse the counter of another type. I guess the algorithm doesn't realize something changed when I just change an argument and not the entire function?
Pass only the first parameter, don't pass the second one at all. Why do you pass it if you don't use it?
Ah, and I get what you're saying. You need for the component to be fully reset when you change the type, right?
If so, the easiest is to add ^{:key type}
in front of [test-wrapper ...]
.
Unless you want to preserve the X counter when switching X -> Y -> X. Although that shouldn't work in your wrapper-based solution either.
The second par is only there because the original fn had it. Forgot to remove it. Ah so I can pass it the key so it knows when to remount the component. That makes a lot of sense. Thanks. No, I do not need to preserve the atom, so the key solution works.
hi, what's the reagent way of dynamically setting and clearing js Intervals. If I declare one in a let then clear it, I lose the reference to it if I set a new one, and I can't clear the newly created one. Can I put a function in a named atom and work with that? It doesn't seem to work.