Fork me on GitHub
#reagent
<
2023-01-24
>
Lycheese14:01:52

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]))])))

Lycheese15:01:40

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))])))

Lycheese17:01:45

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?

p-himik17:01:40

Pass only the first parameter, don't pass the second one at all. Why do you pass it if you don't use it?

p-himik17:01:38

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 ...].

👍 2
p-himik17:01:22

Unless you want to preserve the X counter when switching X -> Y -> X. Although that shouldn't work in your wrapper-based solution either.

Lycheese17:01:52

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.

👍 2
jcb21:01:37

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.

p-himik21:01:54

Same deal as with the state - put the ID where you'd put the state. So you'd have to use with-let or form-2/form-3 components.

jcb20:01:45

Thanks @U2FRKM4TW!

👍 2