OM

Posted by moodyharsh on 2016-06-30

Om is built on three ideas to deal with async shit in clojurescript.

1) Messaging
2) State Management
3) Reactive UI

tl;dr UI -> EVENTS -> STATE -> UI

Reactive UI

This is built on top of ReactJS.
UI is divided into components.

Each component takes a cursor(more on that later).
And has some,

  • rendering code
    rendering code can look like dom/div(default), :div(hiccup) or enlive
  • life cycle hooks where you can place dom event listeners and state change listeners

Initialization of component calls,
IInitState
IWillMount
IDidMount.

Every time a cursor’s state changes a component is rendered, as per the life cycle,
IWillUpdate
IRender or IRenderState
IDidUpdate.

Components are organized as a tree for some fancy optimization purposes.
See,
root - builds the first component
build
component
graft.

State Management

The entire application state and data is an atom blob.
Om gives you cursors which are pointers(paths) to a subset of the blob.

Om also has component local states, which are not stored in the blob.
See,
set-state!
get-state!
props.

It is much simpler to depend on cursors for everything, IMHO.

Om also has truly global state sharing with,
get-shared which gets the :shared argument passed to root.

Cursors are manipulated safely by om API,
update!
transact! you can use a :tx-listen while building root to listen to all transactions
and get-in, assoc-in from clojurescript.

You can extend the ICursor Protocol to come up with your own idea of cursors.

Messaging

Messaging is possible because of core.async, which provides channels and goroutines.
There is no limit to the number of channels and goroutines unless you are using old browsers.
goroutines look alot like threads.

Every component can have channels or channels can be global.
Global channels and goroutines makes it easier to refactor code into multimethods later, IMHO.

Instead of dealing with callbacks in dom event listeners you put! things into channels as events.
In a goroutine you <! on a channel to listen to all the events and act upon them.

Events are acted upon and send further events, finally making changes to the state which call,
IWillUpdate
IRender or IRenderState
IDidUpdate.

Good place to start go(routines),
IWillMount.

Testing and Mocking are greatly simplified using the messaging paradigm.