Skip to content
This repository has been archived by the owner on Oct 17, 2020. It is now read-only.
/ remit Public archive

A tiny (experimental) ClojureScript event-handling library using core.async

Notifications You must be signed in to change notification settings

pointslope/remit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Remit

A tiny Clojure / ClojureScript event-handling library using core.async

Getting It

remit is available on Clojars:

Clojars Project

Motivation

We like reframe's approach to building ClojureScript SPAs using Reagent. In particular, we love the idea of the unidirectional reactive loop. Like reframe's author, we have found that emitting events and having them handle state changes makes it easier to reason about our code. This project takes a slightly different approach to the central event dispatch, however:

  • events are maps

when you emit an event, we create a map containing two keys :event and :data. the :event key specifies the name of the event passed as the first argument to emit. the :data key contains any (optional) data you might have passed as the second argument to emit.

  • event maps are published onto core.async channels using pub/sub

we feel that this provides for greater flexibility by allowing multiple event handlers for a single event, and dynamic event un/subscription.

  • emit/subscribe don't know about your app-db

we didn't feel it was appropriate for an event library to manage your state atom. we did, however, ship an event-map-middleware which makes it easy for you to add your app-db atom to the event map (much the way we do in Ring apps).

;;; Write something like this...
(defn wrap-db
  "Adds the app-db to the event map under the :db key"
  [handler]
  (-> handler
    (event-map-middleware :db app-db)))

(subscribe :missiles-launched
           (wrap-db
             (fn [{db :db {num :icbms} :data}]
               (swap! db #(update-in % [:missiles] (partial + num))))))

Why not simply use DOM event handlers?

DOM events like :on-click live at a different level of abstraction. They are passed a browser-oriented event object (React synthetic event to be precise). By defining events that are application-centric instead of browser-centric, we force the DOM event handler to parse out and repackage information using keys that make more sense to the application domain. Also, it helps us resist the temptation to push logic that changes application state inside of our view components. Component-local state can and should still be managed by the components, but not app state. We can also have several browser events emit the same application event. For instance, both an :on-click and :key-down could emit a :missiles-launched event.

Maturity

This is a very young project that we are using to vet out our ideas about developing SPAs with reagent. It has not been significantly battle tested, blah, blah, blah. Oh, what the hell—just go ahead and try it out. The whole library is under 150 lines of code including docstrings. If you encounter a bug, please open an issue (or better yet submit a pull request) and we'll get right to fixing it.

Copyright

Copyright 2015-2016 Point Slope, LLC

Licensed under the terms of the Eclipse Public License (same as Clojure & ClojureScript)

About

A tiny (experimental) ClojureScript event-handling library using core.async

Resources

Stars

Watchers

Forks

Packages

No packages published