Fork me on GitHub

re-frame guys, is there a good example out there how to test event handlers and subscribers?


Perhaps you can tell where you are having issues testing them specifically, but the easiest solution for non cofx handlers and subscriptions is just to separate the definition of the function and the declaration of it as a handler


So (reg-event-db :something handler)


(defn handler [db args] ... return new db ...)


Then just test it like any other function, feeding it inputs that match possible app states and what you accept as data for the event


That's neat; I'll earmark it


its possible to test the handlers and subscriptions from the JVM using that.


runs pretty fast


Guys, I have a beginner question; Is it possible to develop a migratable project with no changes. React and web.


@scknkkrer Can you rephrase that question? Not sure what you mean


I have a question about view-related data, e.g. dynamic class names. Let’s say I have a list of todos, some of them are done, some of them are not. Based on their donness I want to apply a CSS class - either a class of todo-completed when an item is done or just todo otherwise. My todo-item view subscribes to a subscription, gets item’s data back - the piece of that data that we care about is a boolean done? based on which I can create a class name: (if done? “todo-completed” “todo”). My question is - should this small if-statement live as a separate subscription providing a string to be used as css-class back to the view or should I just use it directly in my view? used directly:

(defn todo-item
 (let [{:keys [done?]} @(re-frame/subscribe [:todo-item id])
       item-class (if done? "todo-completed" "todo")]
  [:div {:class item-class}
   "Hello, I'm a todo-item"]))
subsciption returining a class name:
(defn todo-item
 (let [item-class @(re-frame/subscribe [:todo-item-class id])]
  [:div {:class item-class}
   "Hello, I'm a todo-item"]))
Subscribing for stuff like class names and other markup attrs will greatly increase number of subs as my app grows. At the same time, this class name is not necessarily a part of the global state - it is part of this particular view - so maybe I should keep it this way?


@smogg I think you'd use the first approach


obtain done? via the subscription, and then use it to compute the class


In my world, the view function should compute everything to do with the visual representation - the hiccup, the classes, etc. A subscription is like a database query. Obtaining the data needed.


So :done? is "needed data" ... that is produced by the subscription But the class is part of the view's computations. The view knows about CSS etc. It knows how to use :done? to deliver the right visual representation


yeah, that makes sense - thanks @mikethompson


Got a question about the order of events and views: I have an event that updates some data which updates the DOM, that event also dispatches another event that reads changes off the DOM. Is there anyway to ensure that the second event is ran after all the subs and views? My current workaround is to use a :dispatch-later with a small delay to ensure the second event is schedueled last but is there a better way to handle this?


@akiroz can you give an example of what you trying to do with this type of behavior? Maybe a use case? In general, items that need to read the DOM after a render are part of the did-update lifecycle event on the component involved.


@ckirkendall the first event updates stuff on a canvas, the second one saves a jpeg from the canvas if certain conditions are met and uploads it to the server.


ok wrap the canvas in a reagent component that listens fires the event to check and save in the did-mount and did-update lifecycle events.


that way the event is only ever fired when the canvas renders


well actually, I have multiple canvases and I need to save an image of those canvases concatenated horizontally...


I would dispatch on each render of any of the three and the handler can use a debounced function to make sure multiple calls don’t cause issues.


You loose the purity of the handler but it provides a clean structure for dispatch


hmm, that sounds like a pretty good solution~ I wonder if we should support event debouncing in re-frame....


In my setup I have an interceptor that I can debounce dispatch to


I think debounce dispatch would be awesome as a core feature.


oh cool~ mind sharing your debounce interceptor?


I need to check with my client but I suspect I can.


thanks~ 🙂


Note: I had to remove some stuff around transaction tracking so it is possible I introduced bugs.


@akiroz - one of my friends mentioned it might be better to have this structure for :debounce vs the nested vectors like I show above. [{:event [:event-id arg1 arg2] :timeout 100} {:event [:event-id2 a2 a3] :timeout 200}]


Hey, was hoping to use re-frame's async-flow-fx to coordinate a workflow without using promises. Wondering if the expected behavior for doing a [{:when :seen? :events [:event-1 :event2] :dispatch [:do-finish]} would be to wait until both event-1 and event-2 have fired and then fire do-finish?


nvm just noticed :seen-all-of? sry


@ckirkendall Awesome, thanks for all the help~ 🙂