Skip to content

0.9.1 (2016.12.20)


  • #296 Dynamic subscriptions weren't working in re-frame 0.9.0. This has been rectified. The hosts responsible have been taken underground for reprocessing.

0.9.0 (2016.12.15) - The Dolores Release

Welcome, board members. Dr Ford has created a new 6-part narrative, and Bernard some infographics. Anyone seen Dolores?


  • The README and /docs have been substantially reworked.
  • #218 Make it okay to use subscribe in Form-1 components. This is a big deal.


  • Due to the new tracing features using goog-define (described below), re-frame now requires ClojureScript 1.7.48 or above. See Parameterizing ClojureScript Builds for more information.



  • #200 Remove trailing spaces from console logging
  • Add re-frame.loggers/get-loggers function to well, you know.
  • Added experimental tracing features. These are subject to change and remain undocumented at the moment. By default they are disabled, and will be completely compiled out by advanced optimisations. To enable them, set a :closure-defines key to {"re_frame.trace.trace_enabled_QMARK_" true}
  • #223 When using make-restore-fn, dispose of any subscriptions that were created after the restore function was created.
  • #283 Make trim-v interceptor symmetrical, so it adds the missing event id back on to the :event coeffect in the :after function.


  • #259 Fix a bug where registering a subscription would create and close over dependent subscriptions, meaning that they would never be garbage collected, and doing more work than necessary.
  • Fix a bug where subscribing to a subscription that didn't exist would throw an exception, instead of returning nil.
  • #248 Provide after interceptor with db coeffect, if no db effect was produced.
  • #278 Provide enrich interceptor with db coeffect, if no db effect was produced.

0.8.0 (2016.08.19) - The Walnuts Release

Staying on the leading edge of new buzzwords is obviously critical for any framework. Angular's terrifying faceplant is a sobering reminder to us all. With this release, re-frame's already impressive buzzword muscles bulge further with new walnuts like "effects", "coeffects", "interceptors" and "de-duplicated signal graph". I know, right?

Some may even find these new features useful.

Joking aside, this is a substantial release which will change how you use re-frame.


  • re-frame subscriptions are now de-duplicated. As a result, many Signal graphs will be more efficient. The new behaviour better matches programmer intuitions about what "should" happen.

    Each subscription causes a handler to execute, producing a reactive stream of updates. Two calls to (subscribe [:some :query]) results in two copies of the same subscription handler running, each delivering a stream of updates. Now, if these two subscriptions were running at the same time, this would be inefficient. Both handlers would be doing the same computations and delivering the same stream of updates. Unnecessary, duplicate work.

    Starting with this version, this sort of duplication has been eliminated. Two, or more, concurrent subscriptions for the same query will now source reactive updates from the one executing handler.

    So, how do we know if two subscriptions are "the same"? Answer: two subscriptions are the same if their query vectors test = to each other.

    So, these two subscriptions are not "the same": [:some-event 42] [:some-event "blah"]. Even though they involve the same event id, :some-event, the query vectors do not test =.

  • added a new subscription handler registration function called re-frame.core/reg-sub. It is an alternative to re-frame.core/register-sub (now renamed to re-frame.core/reg-sub-raw). reg-sub is significantly easier to use and understand, while often also being more performant. The design has really fallen out nicely and we're delighted with it.

    With reg-sub, you no longer need to use reaction explicitly. Subscription handlers are now pure which makes them easier to understand, trace and test etc. Plus, as you'll see in the docs, there is some gratuitous syntactic sugar. Who doesn't like sugar?

    At this point, the todomvc example represents the best tutorial on the subject:

  • re-frame now supports the notion of Event Handlers accepting coeffects and returning effects.
    There's now three kinds of event handlers: -db, -fx and -ctx.
    For a tutorial see:

    For Effect Handler examples see:

  • You can now run and debug re-frame tests on the JVM.

    Just to be clear: this does not mean you can run re-frame apps on the JVM (there's no React or Reagent available). But you can debug your event handler tests using full JVM tooling goodness.

    @samroberton and @escherize have provided the thought leadership and drive here. They converted re-frame to .cljc, supplying pluggable interop for both the js and jvm platforms.

    Further, they have worked with @danielcompton to create a library of testing utilities which will hopefully evolve into a nice step forward on both platforms:

    Work is ongoing in this area.

  • the undo/redo features buried in re-frame has been factored out into a standalone library.

    undo and redo have been a part of re-frame from the beginning, but they have never officially been made a part of the API, and have not been documented. So it nice to see it available, and fully documented.

    This new library includes various enhancements over that which previously existed, and it works in with effectful handlers described above.

  • Middleware is dead, long live Interceptors.

    Up until now, re-frame has allowed you to decorate event handlers with middleware which looked after the cross cutting concerns of tracing, undo/redo, validation, etc. This has proved a neat and successful part of the framework. We thought we were happy.

    But recently @steveb8n gave a cljsyd talk on Pedestal's Interceptor pattern which suddenly transformed them from arcane to delightfully simple in 20 mins. Interceptors are really "middleware via data" rather than "middleware via higher order functions". So it is another way of doing the same thing, but thanks to @steveb8n Interceptors appear a more flexible base, and simpler.

    Interceptors also dovetail really nicely with the effects and coeffects story which has emerged in re-frame through this 0.8.0 release.


  • we now have a logo designed by Sketch Maester @martinklepsch. Thank you Martin! But remember, no good deed ever goes unpunished - we'll be pestering you every time from now on :-)


  • requires Reagent >= v0.6.0

  • re-frame.core/register-handler has been renamed re-frame.core/reg-event-db. There's now three kinds of event-handlers, -db, -fx and -ctx. Event handlers of the 2nd and 3rd kinds should be registered via the new registration functions re-frame.core/reg-event-fx and re-frame.core/reg-event-ctx

  • re-frame.core/register-sub has been renamed re-frame.core/reg-sub-raw. This is to indicate that this kind of registration is now considered the low level, close to the metal way to create subscriptions handlers. This release introduced reg-sub which becomes the preferred way to register subscription handlers.

  • middlewares have been replaced by Interceptors. In day to day use, there's a good chance you won't notice the change UNLESS:

    1. You have written your own middleware. If so, you'll have to rewrite it. See how the builtin interceptors are done.

    2. You explicitly use comp to compose middleware like this: clj (reg-event-db :some-id (comp debug tim-v) ;; <-- change to [debug trim-v] (fn [db event] ...))

  • if you have previously used the undo/redo capabilities buried in re-frame, be aware they have extracted into a sibling library:

  • By default, re-frame uses js/console functions like error and warn when logging, but you can supply alternative functions using re-frame.core/set-loggers!.

    With this release, any alternatives you supply will be called with different parameters. Previously loggers were called with a single str parameter but now they are expected to act like console.log itself and take variadic, non string params. Sorry to break things, but we are trying to maximise use of cljs-devtools and information is lost when strings are output, instead of actual data.

    Of course, you need only worry about this if you are using re-frame.core/set-loggers! to hook in your own loggers. If you are, then, to transition, you'll need to tweak like this: ``` ;; your old log function might have looked like this. Single string parameter. (defn my-logger [s] (do-something-with s))

    ;; your new version will have variadic params, and turn them into a string (defn my-logger [& args] (do-something-with (apply str args)) ```


  • Bug fix: post-event-callbacks were not called when dispatch-sync was called.
  • added new API re-frame.core/clear-post-event-callback which de-registers a callback previously added by re-frame.core/add-post-event-callback
  • when an event-handler makes no change to app-db, the debug middleware now logs a single line saying so, rather than a "group". Makes it slightly easier to grok the absence of change.
  • Standardised test namespaces: renamed to use -test suffix and moved to eliminate redundant /test folder
  • Added cljs.test based tests via browser/html. These mimic original karma tests. NOTE: previous lein aliases once and auto have been replaced by test-once , test-auto & karma-once see

0.7.0 (2016-03-14)

Breaking: - removed middleware log-ex. It is no longer needed because browsers now correctly report the throw site of re-thrown exceptions. In the unlikely event that you absolutely still need it, the source for log-ex is still in middleware.cljs, commented out. Just transfer it to your project.

  • debug middleware now produces slightly different output (to console). So no code will need to change, just your expectations of what you see in console. Previously all console output from an event handler was put into the one console group, which could lead to exceptions being hidden (down in a closed group).

Improvements: - added one tick of extra pause when events have :flush-dom metadata. Previously, there were odd times when the pause wasn't long enough to ensure redraws. - now compatible with Reagent 0.6.0 (but this not fully tested) while remaining backwards compatible with Reagent v0.5.1 - #138 Switch to using CircleCI and automated testing with Karma

Fixed: - #149 Undo now discards oldest undo states, not the newest ones.