This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-07-31
Channels
- # announcements (1)
- # beginners (171)
- # cider (51)
- # clj-kondo (40)
- # cljsrn (5)
- # clojure (68)
- # clojure-dev (42)
- # clojure-europe (2)
- # clojure-italy (20)
- # clojure-spec (2)
- # clojure-uk (141)
- # clojurescript (19)
- # community-development (4)
- # core-async (17)
- # core-logic (3)
- # cursive (11)
- # data-science (1)
- # datomic (7)
- # defnpodcast (2)
- # figwheel (9)
- # figwheel-main (2)
- # fulcro (15)
- # graphql (21)
- # jackdaw (3)
- # joker (11)
- # juxt (1)
- # luminus (12)
- # off-topic (2)
- # pathom (73)
- # pedestal (2)
- # re-frame (41)
- # reagent (14)
- # reitit (4)
- # shadow-cljs (39)
- # tools-deps (4)
Per my earlier question about visualizing a signal graph that has become spaghetti, here’s a hacky version of extracting it as data to feed into graphviz: https://gist.github.com/rgm/1b44f546c9ff7cccaeddb7b73d4a4291
it’d probably be useful to have this kind of viz for the other direction, where effects dispatch effects, to pick up eg. :dispatch
, :dispatch-n
and :dispatch-later
effects.
@rgm That’s cool - I’d add that to my projects (although I would probably be more interested in the other direction - event effects that call other events). For that, it may be possible to add an interceptor and tap into the after
function, put it at the front of your chain and build up a graph after interacting with the app for a bit.
Oh, that’s not a bad idea for that direction. It occurred to me too that since I’m defining the subs, I could make some higher-order fn that creates the signal-generating fn for an L3. Other than disconnected nodes (L2s that aren’t used by an L3) that’s where all the info is.
this all has me seeing a ton of symmetry on event/effect flow and subscription flow, but there’s a weird lack of it on the subscription side in that there’s not really anything like interceptors (I don’t think)
Hey everyone, I need some ideas. I'm trying to make an event which dispatches a notification if and only if the variable changes:
(rf/reg-event-fx
:good-http-result
(fn [cofx [_ result]]
(println (str "Successful HTTP-GET: " result))
{ :db (assoc (:db cofx) :success-http-result result)
:dispatch [:set-connection-status true]}))
(rf/reg-event-fx
:bad-http-result
(fn [cofx [_ result]]
(println (str "Failed HTTP-GET:" result))
{ :db (assoc (:db cofx) :failure-http-result result)
:dispatch [:set-connection-status false]}))
(rf/reg-event-fx
:set-connection-status
(fn [cofx [_ status]]
{ :db (assoc (:db cofx)
:connection-status status)
:dispatch [:new-notification
["Disconnected from server" "Please try again later." "is-danger"]]}))
So when a http request occurs, I want dispatch an event called 'set-connection-status' to keep an eye on the status of the last request. If this request CHANGES from false to true, I want to send a notification saying 'reconnected' or something, and likewise if it WAS true but is now false I want it to dispatch the event as shown above.
I could make a complex sequence of events to force order, but I wanted to know if there's any techniques that I don't know about for doing something like this?I'm thinking I do a 'pre-set-connection-status' where I move the current status to a variable called 'last status', then in the actual 'set-connection-status' I then override the current variable and use the past and current value inside my dispatch function.. question is.. I don't know if this is the easiest way
(rf/reg-event-fx
:set-connection-status
(fn [cofx [_ status]]
(let [current-status (get-in cofx [:db :connection-status])]
(cond-> {:db (assoc (:db cofx) :connection-status status)}
(not= status current-status)
(assoc :dispatch [:new-notification
["Disconnected from server"
"Please try again later."
"is-danger"]])))))
^ looks right to me, the idea is to conditionally add the dispatch effect if the status in the db is different from the status in the event
okay let me study this as it's some new information to me
So what really is the difference between cond->
and if
, I know that ->
just allows you to write things a little nicer, but is that the only reason here?
You could write that with if
but you’d be duplicating the :db
value. cond->
differs a few ways but you can match multiple conditions and modify the threaded value for each truthy one.
Okay! I think I got it! Thank you!
So out of all of this, I didn't realise the fx
registration was just a function, I thought it had to be a function which returned a map
but that's very impressive that it is just a function!
It is just a function, but to play nicely with re-frame, it should return either a map or nil.
I just tested it, it works perfect!
Thank you everyone
by the way, cond->
is really useful if you need to build some kind of map that omits any keys that have nil values.
(defn make-opts
[active? selected? modified?]
(cond-> {}
active? (assoc :active "active")
selected? (assoc :selected "selected")
modified? (assoc :modified "modified")))
=> #'user/make-opts
(prn (make-opts :active nil nil))
{:active "active"}
=> nil
(prn (make-opts nil :selected :modified))
{:selected "selected", :modified "modified"}
=> nil
(prn (make-opts :active nil :modified))
{:active "active", :modified "modified"}
=> nil
So rf/reg-event-fx
handlers do return maps. the result of
(cond-> {:db (assoc (:db cofx) :connection-status status)}
(not= status current-status)
(assoc :dispatch [:new-notification
["Disconnected from server"
"Please try again later."
"is-danger"]]))
will be {:db updated-db}
or {:db updated-db, :dispatch conditional-dispatch}
I only learned about it around a year ago myself, and it’s my new favorite Clojure function. 🙂
I get it, I worked though it
that's very powerful stuff
I need to go and get some more lemonade while I digest it
to add on to what oconn is saying, it’s important to note that your reg-event-fx
function can return nil, in which case nothing changes, but if your reg-event-db
function ever returns nil, it will wipe out your app-db and give you some very strange symptoms.
and I’ll quit dumping information overload now. 😄
because db must return the new app state?
and nil = {}
?
Right, the reg-event-db
function needs to return the new app-db state (or at least the old state), but the reg-event-fx
function result goes to an internal function that basically says “If there’s a :db key then update the app-db value, if there’s a :dispatch key then dispatch an event, …” etc.
This sounds dumb but so far I've only dispatched events during on-click and on interval.. Is there any way to dispatch an event on component load? I have a forum component which renders the forum, I want to send a http-get request to get some data and the subscribe for the response
Can I just do
(defn forum
[]
(rf/dispatch ..)
(let [posts @(rf/subscribe ..
[:div#forum
...
or is there a better way?I think that one will re-dispatch every time anything inside the form changes (which may be what you want if your forum component only renders a read-only view of the current contents of the forum). If that's not what you want, you can achieve a one-shot dispatch like this:
(defn forum
[]
(rf/dispatch ..)
(fn []
(let [posts @(rf/subscribe ..
[:div#forum ...
Almost identical to yours except for the inner anonymous function, which re-frame will use as the rendering function every time the contents of the forum change.
hmm, no I think the one shot dispatch is what I want, the user will refresh if tha'ts what they intend to do