This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-06-04
Channels
- # aleph (24)
- # beginners (60)
- # cider (20)
- # clara (4)
- # cljs-dev (13)
- # cljsrn (4)
- # clojure (66)
- # clojure-italy (32)
- # clojure-nl (4)
- # clojure-serbia (1)
- # clojure-uk (207)
- # clojurescript (115)
- # cursive (3)
- # datomic (36)
- # defnpodcast (1)
- # duct (15)
- # fulcro (14)
- # graphql (8)
- # lein-figwheel (1)
- # leiningen (4)
- # off-topic (140)
- # pedestal (40)
- # portkey (3)
- # reagent (40)
- # remote-jobs (1)
- # ring (11)
- # shadow-cljs (31)
- # spacemacs (6)
- # sql (65)
- # tools-deps (67)
- # yada (1)
I was trying to generate dynamic number of checkboxes, the state of which is stored in the app state which is an atom which is a list of dicts like this
[{:checked false, :text "Sample text 1"} {:checked false, :text "Sample text 2"} {:checked false, :text "Sample text 3"}]
The function below is expected to generate a checkbox corresponding to the specified index of app’s db (`db`). The function does it jobs and the checkboxes are clickable.
(defn gen-checkbox [index db]
[re-com/checkbox
:label (:text (@db index))
:model (:checked (@db index))
:on-change #((swap! db assoc-in [index :checked] (not(:checked (@db index)))))
])
However, I get this error when I click on any checkbox.
Uncaught Error: Assert failed: Reaction is read only; on-set is not allowed
The error occurs at swap!
. Can some one point out where I am doing wrong?:on-change #((swap! db assoc-in [index :checked] (not(:checked (@db index)))))
should be
:on-change #(swap! db assoc-in [index :checked] (not(:checked (@db index))))
Ie. Remove a set of parens
Thanks @mikethompson. However, the error is still occuring.
Uncaught Error: Assert failed: Reaction is read only; on-set is not allowed
(fn? (.-on-set a))
at reagent.ratom.Reaction.cljs$core$IReset$_reset_BANG_$arity$2
there are too many things going on in that snippet. I'd narrow it down to something simpler
@pesterhazy thanks! I am relatively new to clojure and reagent. Is there a better way to generate a dynamic number of checkboxes and save the states in the app’s state?
it looks fine to me
one thing we don't see is what db
is here. It looks like it's not the Ratom but a Reaction
@devinbox.vishnu As @pesterhazy suggests, it looks to me that your db
is a readonly Reaction
and not a read/write ratom
In which case, your (write-full) attempt at a swap!
is failing with that error.
I want to set up an async polling process that runs while my reagent
component is on the screen, and is removed when it isn’t. Is there a canonical example for this sort of thing? I’m guessing a form-3 component can take me at least some of the way, maybe all of the way?
@reefersleep you can definitely do that with form-3 by using :component-did-mount
and :component-will-unmount
. but i think you can also do it in a more clojurey way using with-let
and finally
@lee.justin.m what’s with-let
? I don’t see it anywhere.
Ah, I thought we were talking vanilla Clojure! reads
That’s just brilliant, exactly what I need! Cheers @lee.justin.m!
@reefersleep if using re-frame, can take a peak at re-pollsive https://github.com/gadfly361/re-pollsive
Ah yes. I would, only this particular project is reagent + custom stuff on top, and it’s a work project 🙂
hmmm @lee.justin.m it’s not working how it should, but I think it’s to do with my lack of understanding of core async.
I’ve with-let
a call to go-loop
. The finally
block is called, and inside it, I use close!
to kill the loop, only it doesn’t kill the loop.
I was unsure of whether using close!
was a correct move, since the documentation state that it works on channels, and I’m unsure of what a loop is (maybe a channel?)
But I used close!
to ensure that figwheel-reload wouldn’t start several loops, and that seemed to work.
I probably just need to rethink my async code 🙂
i quit using core.async because it find its metaphors to be the wrong solution for me and it introduces a lot of complexity, so i’m the wrong guy to ask. but, generally, i recall a discussion that core.async is not cancellable (?)
i assume what you are doing is pumping into a channel inside of the setInterval callback?
consider just signaling through the standard reagent/atom mechanisms and then just cancelling the interval in the finally block. so much simpler
@lee.justin.m I just realized that I could do the same thing this morning 🍻 I started off with (code that does not close the go-routine):
(reagent/with-let [my-timeout-routine (go-loop []
(<! (timeout 2000))
(do-my-work)
(recur))]
[my-component]
(finally (close! my-timeout-routine)))
I did it differently, like this, and it works as expected:
(reagent/with-let [keep-timing-out? (atom true)
my-timeout-routine (go-loop []
(when @keep-timing-out?
(<! (timeout 2000))
(do-my-work)
(recur)))]
[my-component]
(finally (swap! keep-timing-out? not)))
Is this what you were thinking about, too?Brilliant! Thanks for the help! I’ll be sure to add with-let
and finally
to my arsenal of state management 🙂
Hi all, I am curious about the caching semantics of the reagent.core/with-let
macro, specifically with respect to the react will-mount
lifecycle method. What I'm seeing is that the values with-let
macro are evaluated before the component is mounted on the dom, but also on each browser reload. The will-mount
lifecycle method however is not evaluated on every reload, just a hard refresh, when a new component is actually created. I was using with-let
as a convenience over the will-mount
method, but clearly there's some important, but not obvious difference.
I’m not sure I follow the distinction between a “browser reload” and “just a hard refresh”?
certainly though, they have different semantics. the lifecycle events are managed by react and with-let happens on top of all that. it would be interesting if you found a difference between a form-2 component and a with-let component
@lee.justin.m, sorry, the way I put it was unclear, it's not a browser reload, but a code reload, such as when figwheel or a boot tasks automatically reloads code in the browser. No new components are made in this case, and so will-mount
will not run. However, the values in with-let
are re-evaluated.
And the with-let
semantics do indeed appear different than form 2. The values in a with-let
are re-evaluated across code reloads, even when no new components are created. The context in a form 2 component is not.
@lee.justin.m I just realized that I could do the same thing this morning 🍻 I started off with (code that does not close the go-routine):
(reagent/with-let [my-timeout-routine (go-loop []
(<! (timeout 2000))
(do-my-work)
(recur))]
[my-component]
(finally (close! my-timeout-routine)))
I did it differently, like this, and it works as expected:
(reagent/with-let [keep-timing-out? (atom true)
my-timeout-routine (go-loop []
(when @keep-timing-out?
(<! (timeout 2000))
(do-my-work)
(recur)))]
[my-component]
(finally (swap! keep-timing-out? not)))
Is this what you were thinking about, too?