Thanks both - it does. My brain wasn't really engaged when I asked the question. The salient point is that there are levels/layers in play here.
I like your idea that dispatched events are application level events.. I might get shot for saying this, but I actually don't care particularly about re-usable components as IME the effort required to get them truly re-usable is less than the churn required to adapt them to a new framework - maybe I am just not being strict/clean enough... I do care very much about increasing ignorance/decoupling everywhere. Unfortunately that ignorance is mostly in my head today it seems :). On 27 March 2015 at 14:03, Daniel Kersten <dkers...@gmail.com> wrote: > I'm currently tinkering with an approach where my code does not dispatch > re-frame events at all, but rather uses my own emit function to emit > signals[1]. I then, separately, have a signal->event map, so the (single > global) signal handler then maps signals to events and dispatches these > events to re-frame. > > What this gives me is that the components don't have to know what the (DOM) > event callbacks actually do. Eg, instead of clicking the "add to list" > button dispatching an [:add-to-list ...] event, it triggers an > :add-to-list/clicked event and its up to the application to map this to the > [:add-to-list ...] event. This way this component can be reused elsewhere by > mapping the signal to whatever it makes sense for it to be mapped to. > > This indirection also means you can map one signal to trigger multiple > re-frame events, although I haven't played with this enough yet to know if > that is desirable or not. > > I like to think of re-frame events and handlers as the applications actions > or capabilities - that is, the things that you can do. That way it makes > sense that there is a 1:1 relationship between events and event handlers (eg > only one handler can handle [:add-to-list ...]). That way, components emit > "this thing just happened" signals which are mapped to "this outcome should > be performed" actions/capabilities. > > Obviously reusable components can't always be made in isolation of the > actions that they trigger, especially if they need to maintain > transient/intermediary state. For this I like to define the component > specific handlers as namespaced keywords, eg :my-list-editor/add-to-list > > I'm still undecided if such events should be dispatched directly or go > through the signal indirection. > > Some final thing to note about the approach I'm investigating: > 1. My signal->event mapper can take an optional (pure) function to convert > signal parameters to whatever data the handler expects. > 2. I like to keep my handler functions pure too and do any side-effects (eg > server comm or dispatching new events/emitting signals) in middleware. > > Hope that gives you some ideas. > > [1] I haven't got the terminology down yet :) I'm calling them signals for > now because they're kinda like Qt's signals & slots, but I dunno if they > really fit into the definition of signals from the FRP world. > > On Fri, 27 Mar 2015 at 13:58 Khalid Jebbari <khalid.jebb...@gmail.com> > wrote: >> >> On Friday, March 27, 2015 at 2:39:37 PM UTC+1, Jamie Orchard-Hays wrote: >> > Does it make sense to pass the reusable component's context as an >> > argument to it? ie, >> > >> > (defn ReusableComponent [some-context] .... ) >> > >> > Jamie >> > >> > On Mar 27, 2015, at 8:54 AM, Colin Yates <colin.ya...@gmail.com> wrote: >> > >> > > In re-frame event dispatching is handled by (dispatch [:discriminator >> > > detail]). A corresponding (register-handler :discriminator (fn [db [_ >> > > detail]]) then reacts to that dispatched event. >> > > >> > > My question is how are people managing this with re-usable components? >> > > For example, I have a tree and when selecting a node in that tree >> > > something >> > > should happen. But this is where it gets all polymorphic as _what_ >> > > happens >> > > depends on the client who instantiated the tree. I can see the following >> > > ways forward: >> > > >> > > - tree is configured with a 'context' key which is combined with the >> > > discriminator so rather than the tree emitting :node-selected it emits >> > > :consumer-a-node-selected. Consumer a can then handle >> > > consumer-a-node-selected and consumer b can handle (go on, guess) >> > > consumer-b-node-selected >> > > - a variation on the above involving writing your own dispatching >> > > logic... >> > > - tree doesn't use dispatch as the event bus, rather it takes in an >> > > instance of a Protocol: >> > > IRespondToTree >> > > (on-node-select [this node]) >> > > - tree is parameterised with a map of fns {:node-selected-fn ...} etc. >> > > >> > > How would you all handle it? (I am leaning towards the first one). >> > > >> > > -- >> > > Note that posts from new members are moderated - please be patient >> > > with your first post. >> > > --- >> > > You received this message because you are subscribed to the Google >> > > Groups "ClojureScript" group. >> > > To unsubscribe from this group and stop receiving emails from it, send >> > > an email to clojurescript+unsubscr...@googlegroups.com. >> > > To post to this group, send email to clojurescript@googlegroups.com. >> > > Visit this group at http://groups.google.com/group/clojurescript. >> >> Not sure I'm going to answer the question directly, since I've never used >> re-frame, Reagent or Om. I'm just an experienced React.js developer VERY >> interested with Clojure(Script). >> >> If you want reusable components, whatever wrapper you use around React, >> here's the plan. >> >> You should create 2 types of components : dumb and smart. Dumb components >> do 2 simple things : display stuff and handle input/events. The way they >> handle should be agnostic to any kind of library and should use only >> language-level feature. Functions. So the dumb component use function it's >> been passed and call it with the input/event. The smart components wrap dumb >> components and connect to the outside world with whatever your stack uses >> (channels, events, ratoms, what not). >> >> This way your dumb components are always reusable, whatever stack/project >> they're incorporated in. They can also be displayed in a simple page for >> your graphics or HTML/CSS team to check their look. The smart components >> handle whatever logic you want to put in them. So from a stack/page/project >> to another, only the smart components change, no the dumb ones. This keep UI >> consistent and separate concerns. >> >> Hope it's clear and helpful. >> >> -- >> Note that posts from new members are moderated - please be patient with >> your first post. >> --- >> You received this message because you are subscribed to the Google Groups >> "ClojureScript" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojurescript+unsubscr...@googlegroups.com. >> To post to this group, send email to clojurescript@googlegroups.com. >> Visit this group at http://groups.google.com/group/clojurescript. > > -- > Note that posts from new members are moderated - please be patient with your > first post. > --- > You received this message because you are subscribed to the Google Groups > "ClojureScript" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojurescript+unsubscr...@googlegroups.com. > To post to this group, send email to clojurescript@googlegroups.com. > Visit this group at http://groups.google.com/group/clojurescript. -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at http://groups.google.com/group/clojurescript.