This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-04-09
Channels
- # beginners (108)
- # boot (14)
- # cider (8)
- # clara (13)
- # cljs-dev (63)
- # cljsrn (5)
- # clojure (57)
- # clojure-brasil (1)
- # clojure-italy (69)
- # clojure-losangeles (10)
- # clojure-nl (6)
- # clojure-poland (2)
- # clojure-spec (6)
- # clojure-uk (50)
- # clojurescript (116)
- # core-async (1)
- # cursive (9)
- # data-science (8)
- # datascript (4)
- # datomic (43)
- # duct (2)
- # editors (1)
- # fulcro (29)
- # instaparse (7)
- # jobs (6)
- # keechma (3)
- # mount (16)
- # off-topic (61)
- # om (10)
- # onyx (5)
- # parinfer (17)
- # pedestal (2)
- # portkey (5)
- # quil (2)
- # re-frame (84)
- # reagent (9)
- # remote-jobs (2)
- # ring-swagger (2)
- # shadow-cljs (17)
- # slack-help (1)
- # tools-deps (29)
- # vim (23)
In re-frame, what is the recommended way for a custom reagent component to receive/react to events sent from other components?
@vincent.cantin your UI is a rendering of the current state in app-db
. So components don't really react to events sent by other components. Instead, an event changes app-db
and then that new state in app-db
is rendered
But there are some cases where a component cannot just react to data change and need to receive events, somehow. For those special cases, is there a way for them to register an event handler just for the time where they are mounted on the dom?
Would it be the recommended way to do it?
> where a component cannot just react to data change and need to receive events, somehow For clarity, can you give an example?
a leaflet map (from the js world), wrapped inside a reagent component, and which would want to receive an event like :recenter-view-on-all-marker-but-just-right-now-not-permanently
The event handler needs to have a reference to the right map instance which is created dynamically in the reagent component.
And what does the user do to cause this?
the user push a button located somewhere else on the page.
So that button would emit an event (a normal re-frame event)
And that event would be processed by an event handler
Which would update some state in app-db
to indicate the users preference
And there would be a subscription delivering that state to the view
Then you'd use this sort of arrangement to work with a stateful js component ...
https://github.com/Day8/re-frame/blob/master/docs/Using-Stateful-JS-Components.md
That's the data-driven approach, that does not fit the event's lifecycle.
If the user clicks on the button a second time, the map is expected to recenter again.
I imagine 2 ways to solve my problem, but I don't want to implement something weird, so I want to ask if the solutions are what I am supposed to do or not.
Solution 1: In the :component-will-mount, after the leaflet js object is created, I register an event handler which has the reference to that instance. I unregister it when the reagent component unmount.
Hmm,. Its kinda like its an effecct
You want to effect
(mutate) the Leaflet instance
Solution 2: I add the leaflet js object to the app-db
on mount, and I remove it when I unmount. A permanent event handler is getting the reference from the db.
I see what you mean now about wanting to send an event
to the Leaflet instance
There's something about Solution 1 which seems more correct
But I'd do it via effects
So the event handler returns an effect which says that X should happen to the Leaflet instance (what you call the event to the Leaflet instance)
Uggh. There's going to be a bit of plumbing.
Nothing entirely natural going on here
Yes, so that's why I am thinking that I can not just implement a "reagent component" for leaflet, it has to be a "re-frame component".
Because of the plumbing involved.
Not sure I understand the difference. re-frame uses reagent for components
reagent does *not* cover the events, the domino ...
Thank you for your feedback already.
I'm still not following. But perhaps not important.
So, thinking out aloud ... not completely convinced of this but anyway just speculating :
1. I think your button will have to emit an event [:recenter-view-on-all-marker-but-just-right-now-not-permanently 1234]
where 1234 is the Leaflet instance.
2. then the event handler will have to produce the effect:
{:leaflet-mutation {:id 1234 :mutation :recenter-view-on-all-marker-but-just-right-now-not-permanently}
3. Then you need the effect handler defined for :leaflet-mutation
which has a way to get at the leaflet instance
So now we get into the Leaflet instance getting "registered" cia component-did-mount
with its id of 1234
So the effect handler knows how to get at it.
This is a kinda variation on your two scenarios
Just a thought
That's as close to idomatic re-frame as I can imagine.
The mutation of the Leaflet instance is "a change to the world" so that should be modelled as an effect
But ... its all pretty unusual ... I'm not sure there's really a perfect way. Easiest way might be best.
Gotta go. Good luck
Thank you !
hi everybody. I have a reg-sub-raw
like this:
(rf/reg-sub-raw
::my-sub
(fn [db _]
(rf/dispatch [::me/event-1])
(r/reaction (:my-result @db))))
Is there a way to trigger it on browser back button?@vincent.cantin I have used the approach that @mikethompson references successfully with leaflet and other "stateful" js libs like d3, codemirror etc... ( can't share code atm, not open source yet ) 1. on component-did-mount create the lib instance and attach it to an atom 2. when props update, get the lib from the atom and use it What do you mean when you say "That's the data-driven approach, that does not fit the event's lifecycle"?
@fj.abanses It mean that there is a difference of life cycle between a stored data in the db and an event : The event has a meaning at the time it is fired and it theoretically dies right after being received. Data in the app-db stays until removed. The same event dispatched multiple times consecutively will mean something else than a data set at a given value multiple times.
In my program I am already tracking data from my custom leaflet component to add and remove markers, but events were still needed in addition.
@manuel I think secretary handles that sort of thing, you might want to check that out (https://github.com/gf3/secretary). Also I’d highly recommend not putting a dispatch
inside a subscription — it’s too easy to get yourself into an endless-loop situation that way. If you need your app to respond to events that are not user-generated, you probably want effects (https://github.com/Day8/re-frame/blob/master/docs/Effects.md)
@manutter51 thanks. I am using bidi at the moment, I'll see what I can do.
There’s also the plain old JS hook for the beforeunload
event. Might be able to hook into that somehow, via an effect, though there are serious restrictions on what a beforeunload
handler can do, due to past abuses.
Hi all, is there a common source for this error:
e-frame: no handler registered for effect:
Object { ns: null, name: "event", fqn: "event", _hash: 301435442,
...
I can't find the error. I never dispatch an event called "event" or something else.Happens along dispatching other events.
Do you have a typo somewhere in the map you return from reg-event-fx
?
specifically a typo in a key
Thanks, It was indeed in the coeffects map. If you return them as they come in the argument, they seem to contain more than the :db
key. I now return {:db (:db coeffects)}
and no effect is triggered.
Two small but significant fixes here ^^, 1. ClojureScript MapEntries in 1.10 aren't printed with the blue protocol browser when you're inspecting data 2. Data previews in the Event browser are now 'lazily' printed so we only pay the cost to print the size of string that is viewable, not the entire data structure. If you have a large app-db this will make a big performance difference
@jeaye unfortunately we never do development using ReactNative so we're clueless about it all.
Someone with direct knowledge and experience will have to step up
@jeaye there is a #react-native channel
but yeah, it’s a bit quiet
talking of needing some help though… I need some scrolling care
I’m wondering if some the CSS / flexbox stuff is preventing the scrollTop from having the desired effect so would appreciate some advice
(if I remove the styles it still doesn’t work so I think it’s probably not that)
@jeaye we have good progress on making re-frame-10x work with React Native. Here are the instructions on how to set that up https://gist.github.com/dmitryn/d97f05a0ff2a653d07d696daa4880ad1