This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-02-12
Channels
- # aleph (22)
- # aws (7)
- # babashka (17)
- # beginners (69)
- # chlorine-clover (9)
- # cider (2)
- # clj-kondo (3)
- # cljdoc (30)
- # clojure (113)
- # clojure-dev (30)
- # clojure-europe (11)
- # clojure-italy (2)
- # clojure-nl (16)
- # clojure-spec (1)
- # clojure-sweden (3)
- # clojure-uk (17)
- # clojurescript (77)
- # cryogen (12)
- # data-science (5)
- # datomic (27)
- # duct (2)
- # emacs (37)
- # fulcro (24)
- # graphql (2)
- # kaocha (1)
- # lambdaisland (27)
- # leiningen (4)
- # off-topic (15)
- # onyx (1)
- # other-lisps (3)
- # re-frame (94)
- # reagent (2)
- # reitit (20)
- # ring (1)
- # shadow-cljs (66)
- # spacemacs (5)
- # sql (59)
- # tools-deps (140)
- # vim (1)
- # xtdb (17)
Hi all. This may be a bit of a stretch, but I'm working Redux-Loops, a port of the Elm architecture to Javascript. If I'm remembering correctly, Re-frame uses a very similar architecture, so I'm hoping you guys help me with a question. I've got an event loop. I dispatch events. Event handlers (action reducers in my case) return side effects (as data) to be returned. Here's my conundrum: one of my side-effects is that I subscribe to some kind of stream (for sake of argument, lets say its a websocket connection that notifies me every time a chat message comes in). How do I handle this within the confines of this architecture? Can i dispatch actions directly from side-effecting code? I could see that becoming messy quickly if not tightly controlled.
@d4hines yes, this is how we do it. Why do you think this is a problem? How is it different from an action being dispatched from e.g. a UI event?
Thanks for the clarification. I think this is just a little different than how I'm used to, but on further reflection it makes sense. I'm used to RxJS and observable streams, where you can directly merge different event streams. But this will work great. Thanks!
How can I use a subscription in a callback? I need to get check whether the search term matches. I don't want to trigger a rerender (performance), so I can't use a closure. When I use subscribe it causes a pretty terrible memory leak. 100mb or so for basic use.
Your callback should fire off an event. The event handler will get the app-db and you can just use get-in
to look up the search term.
If for some reason that's not an option, you can save the ratom and call cljs.core/-remove-watch
on it immediately after you get its value.
Actually, it seems that calling -remove-watch
requires some Reagent internals know-how that I don't have, because you have to provide a key for it.
Can you provide any more details about your use case?
You can always call the sub handler directly on app-db
. Although that would be quite "dirty".
My sub is pretty much just get k. So I'm just doing that currently. I'm not sure there seems like an official solution to this.
@manutter51 I'm using a react component, which takes a function predicate prop to determine whether to show an item. This allows me to implement an external search functionality. I don't want to use a closure because it is on a hot path, and running everything twice will tank performance. So I need to be able to statically define my function.
Aha, ok.
So hereās a quick thought just for brainstormingās sake: You probably have a handler that updates the value of the search term in the db. Make your own atom someplace else and have the handler update that value also, so they stay in sync, and use your non-ratom atom in your callback.
This is a common approach for inputs, because each change in app-db triggers all layer 2 subs.
Thatās a good approach, but lately Iāve been storing input values in app-db because then I can make form validation run off of subscriptions, which is pretty cool.
Thatās basically what Iām doing here https://github.com/luciodale/fork but with a pure function rather than subscribing (which will have the same effect in this case)
I really like to keep re-frame out of the input handlers logic .. I just use it for events that involve external components as well .. being on change validation server side, submit events and so on
āApp-Db Liteā¢ā š
Basically youāre just caching out a specific piece of data, without the subscription overhead, as a performance optimization.
Also worth remembering that if you have to dig into Reagent internals to write code, itās going to take similar in-depth knowledge to maintain it.
although re-frame might still hang onto the subscription since it does some caching
dispose!
will remove the cache, along with all of the watchers. It will lead to other usages of the same sub not triggering any re-renders.
I haven't used it, but it might be worth looking at https://github.com/den1k/re-frame-utils/blob/master/src/vimsical/re_frame/cofx/inject.cljc to see if something like that would solve your problem - it's recommended in the docs at https://github.com/day8/re-frame/blob/master/docs/FAQs/UseASubscriptionInAnEventHandler.md
this is very relevant to me since Iām using some subscriptions outside of reagent components (react hooks). I want to nip these memory leaks in the bud
I have a use-reaction
hook that handles that, yes. it uses reagent.core/make-reaction
under the hood so maybe Iām OK
I havenāt noticed any memory leaks yet but itās not a very hot path and I havenāt tested for it specifically
You can check if the subs are left in the cache after the component that uses them is no longer rendered.
But again, if you do that much stuff (more or less internal) around a simple sub, maybe it's worth it to just access app-db
directly.
I haven't tried this yet, but what about binding reagent.core/**ratom-context**
to nil
when you dereference the sub? @dominicm
To me it seems pretty obvious if you think about how a global API like this would be implemented
I'm not even sure what is evil anymore. :grinning_face_with_one_large_and_one_small_eye: I'm curious to at least try that in the morning. I've disconnected for now.
I think thereās a proposal at the heart of this for a public feature in re-frame that allows one to do this
They have this, it is just private: https://github.com/reagent-project/reagent/blob/2027a2d8881bae0567ecf9d4c90550b064a2ad0c/src/reagent/ratom.cljs#L36-L42
Library A uses the internals of library A. Library B uses library A. Why do you think that both libraries are evil? The question is not about global context, but about internals.
If library A uses the internals of library A, that's a-OK. If library B uses the internals of library A (and is not maintained by the same people that maintain A, arguably), that's not good.
That's for sure. And I was arguing about the downsides of the solution with *ratom-context*
, nothing more.
hi, is there something similar to event bubbling in re-frame? I have a component that dispatch an event when clicked but I also need to fire another event from the parent of the component? is that possible?
Are you trying to bubble React events, or re-frame events? When you fire the event on your inner component that dispatches [:event1]
, what are you looking for from the outer component?
I want to know that the click was made inside a button of the inner component in order to dispatch something (an ajax call) in the parent, the problem is I donāt have access to the inner component to modify it
can I have two reg-event-fx with the same name? one in the inner component and the other in the parent?
So you have no control over what happens when the inner component is clicked? Or can you choose what event it is dispatching?
mmm, I donāt want the inner component to know nothing about the outside world
But you can control what events are fired?
If the child component is using just :on-click
or something like that and does not call stopPropagation
, you can have :on-click
on the parent component, and it will be called when you click on the child component.
[:div {:on-click #(js/console.log "Div clicked")}
[:button {:on-click #(js/console.log "Button clicked")}
"Click me"]]
I could, Iām thinking maybe to add a param to the inner component and that param could be a function
I hadnāt tried that, I thought it wasnāt possible
now, Iām filling stupid for asking that, thanks again @p-himik and @U054BUGT4
Assuming you're passing the on-click function to your component, I would lean towards something like [:outer-component [:inner-component {:on-click #(re-frame/dispatch-n [[:inner-event][:outer-event]])}]]
yes, you did, and and google it but I didnāt find anything
@U054BUGT4 There's no dispatch-n
function in re-frame. Only effect.
@U9BUENJ1F Having a playground project where you can check whatever comes to your mind is definitely helpful. Often it's also faster than trying to find an answer online. Especially if you have easy access to the sources of all of the dependencies.
but I could do somthing like this (do (dispath [e1]) (dispath [e2]))
@p-himik Oh yeah, good point - I think I put it into one of my projects as a simple wrapper. You could take the idea though
Yes, you could dispatch two events. Although I bet there's something in re-frame docs justifying against such practice. Debatable.
but I will stick with the :on-click
Personally, I would argue against using bubbling where you can control every component. Seems shaky at best.
I think I ended up taking the code from https://github.com/day8/re-frame/blob/97a5c3795820cd37a976b62e2ac3cb1f626d2467/src/re_frame/fx.cljc#L133 and using the same doseq
logic in the functions I needed to use dispatch-n in
so you donāt recommend bubbling
The other thing you could do is pass a parameter to your inner event for it to dispatch later - (dispatch [:e1 [:e2 :e3]])
- then your inner component event has the logic so that it expects it will be dispatching further events, and you have a central place to deal with more complicated situations (if you are expecting them to come up)
I would stay away from bubbling if I had any other options - re-frame gives you the tools to avoid it for most situations, and I can't see anything but downsides to choosing to use bubbling unless you have no other choice.
ok, I will implement any of your recommendation instead of bubbling
Good luck - feel free to ask more if you run into any issues.
thank you very much to both of you