On Saturday, April 4, 2015 at 9:51:07 AM UTC+11, Karsten Schmidt wrote:
> Thanks, Daniel. Didn't know about `dispatch-sync` and this would
> definitely help to avoid the delay, but the fundamental question to me
> still is how to create reactions to handler changes *outside* reagent
> components. I'm not sure if re-frame or reagent actually supports this
> at all.
>
> AFAIK `(subscribe [:tick])` only makes sense inside a component fn.
> Given the following subscription handler:
>
> (register-sub :tick (fn [db _] (reaction (:tick @db))))
>
> I would like do to something like to do this outside a component:
>
> - subscribe to :tick
> - update dispatch-sync to dependent handler(s)
> - setup more subscriptions (:a, :b, :c ...)
> - have a set of components subscribing to :a, :b, :c etc.
>
> So every time :tick updates, everything will be re-run/re-drawn. The
> reasons why these dependent updates should be in handlers is that some
> of them will require results from earlier (intermediate) handler
> updates.
>
> Maybe I'm barking up the wrong tree here and should just solve this
> via core.async mult/tap or its pub/sub?
>
> On 3 April 2015 at 23:07, Daniel Kersten <[email protected]> wrote:
> > Have you tried using dispatch-sync?
> > https://github.com/Day8/re-frame/wiki/Bootstrap-An-Application#a-cheat and
> > https://github.com/Day8/re-frame/blob/master/src/re_frame/router.cljs#L54
> >
> > On Fri, 3 Apr 2015 at 22:50 Karsten Schmidt <[email protected]> wrote:
> >>
> >> I've been really enjoying my last month working on a largish app based
> >> on re-frame and not run into any probs. However, today I was going to
> >> refactor another project using animation and came across an issue
> >> which I'm somewhat stumped by:
> >>
> >> I created a global tick handler, which is supposed to be an event
> >> generator for various other handlers to update their data in the app
> >> db. Currently this :next-tick handler re-triggers itself like shown
> >> below and runs as predicted (~60Hz via requestAnimationFrame), but for
> >> the purpose of this question this could be triggered at any (lower)
> >> frequency:
> >>
> >> (defn re-trigger-timer [] (reagent/next-tick (fn [] (dispatch
> >> [:next-tick]))))
> >>
> >> (register-handler
> >> :next-tick
> >> (fn [db _]
> >> (re-trigger-timer)
> >> (update db :tick inc)))
> >>
> >> Now I'd like to have other handlers which (dynamically) subscribe to
> >> these tick changes, but they should be run without causing another
> >> 16ms delay caused from using the subscribe/dispatch mechanism - and I
> >> keep drawing a blank how to achieve this w/o modifying
> >> re-frame.db/app-db directly (outside an handler).
> >>
> >> Of course I could create a subscription for the :tick value, run the
> >> related code and return the computed data as derived view during
> >> re-drawing of the related components, but that kind of defeats the
> >> whole purpose and I'd really like these updates to happen in handlers.
> >> I'm sure there's a better way... no?! :)
> >>
> >> Could someone please clarify for me?
> >>
> >> FWIW the demo app in question is here:
> >> http://demo.thi.ng/geom/physics/strands.html
> >>
> >> For starters I'd like to update physics sim via an handler reacting to
> >> :tick changes, but there'll be others too...
Hi Karsten,
First, its really nice to hear that re-frame has worked well for you so far!!
I've read your problem description and summarized it this way:
1. you need to run N different tick event handlers every 16ms.
2. the set of "tick" event handlers changes over time.
Some get added and removed.
To state the problem anther way: you want to register N event handlers for the
one event, but re-frame doesn't allow for that. It only allows one event
handler to to run for an event.
Also, performance is an issue here. You want those tick handlers all run as
soon as possible. No 16ms delay.
If that is a good description of the problem, then we need to look for solution
by asking ... how do I get N event handlers run for the one event?
There's a couple of ways of doing that but they'd all involve you "adding your
own layer to re-frame". Here's one ...
Sketch
------
In app-db, store the list of event handler ids which should be run on each
tick.
(register-handler
:add-tick-handler-id ;; usage: (dispatch [:add-tick-handler-id
:some-other-id])
(fn [db [_ tick-handler-id]
(update-in db [:tick-handlers] conj tick-handler-id)))
(register-handler
:remove-tick-handler
(fn [db [_ tick-handler-id]
...))
;; this happens every tick
(register-handler
:tick
(fn [db v]
(let [hs (map re-frame.handlers/lookup-handler (:tick-handlers db))]
(reduce #(%2 %1 v) db hs)))
--
Mike
--
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/clojurescript.