-
Notifications
You must be signed in to change notification settings - Fork 354
Documentation
The Om life cycle protocols map more or less directly to the life cycle API present in Facebook's React.
Om component functions return reify instances that implement the Om
life cycle protocols. When this is used in a lifecycle protocol it refers
to the reify instance. As a rule of thumb it is not needed and can be discarded.
(defn my-widget [data owner]
(reify
om/IRender
(render [_]
(dom/h1 nil "Hello world!"))))It's important to understand that my-widget will be called many
times. Thus it's an anti-pattern to wrap reify in a let to
allocate stateful entities like core.async channels. Stateful entities
should be stored in component local state - om.core/IInitState or
om.core/IWillMount are good places to do this.
(defprotocol IInitState
(init-state [this]))Called only once on an Om component. Implementations should return a map of initial state.
(defn my-widget [data owner]
(reify
om/IInitState
(init-state [_]
{:text "Hello world!"})
om/IRenderState
(render-state [_ state]
(dom/h1 nil (:text state)))))(defprotocol IWillMount
(will-mount [this]))Called once when the component is about to be mounted into the DOM. A useful place to establish persistent information and control like core.async channels and go loops.
(defprotocol IDidMount
(did-mount [this]))Called once when the component has been mounted into the DOM. The DOM node associated with this component can be retrieved by using (om.core/get-node owner).
This is a good place to initialize persistent information and control that needs the DOM to be present.
(defprotocol IShouldUpdate
(should-update [this next-props next-state]))You should only implement this if you really know what you're doing. Even then you probably shouldn't.
Implementations should return a boolean value. If true then the
component's om.core/IRender or om.core/IRenderState implementation
will be called. This provides the opportunity to prevent components
from re-rendering in response to certain changes in app (props) or local
state. Please note that preventing components from re-rendering
in response to props or state change could result in the DOM being out
of sync with application or local state.
next-props is the next application state that the component is
associated with. next-state is the next component local state, it is
always a map.
In your implementation if you wish to detect prop transitions you
must use om.core/get-props to get the previous props. This is because your component
constructor function is called with the updated props.
(defprotocol IWillReceiveProps
(will-receive-props [this next-props]))Not called on the first render, will be called on all subsequent renders. This is a good place to detect app state changes and make updates to local component state using om/set-state! or om/update-state!.
next-props is the next application state associated with this
component.
In your implementation if you wish to detect prop transitions you
must use om.core/get-props to get the previous props. This is
because your component constructor function is called with the
updated props.
(defprotocol IWillUpdate
(will-update [this next-props next-state]))Not called on the first render, will be called on all subsequent renders. This is a good place to detect and act on state transitions.
next-props is the next application state associated with this
component. next-state is the next component local state, it is
always a map.
In your implementation if you wish to detect prop transitions you
must use om.core/get-props to get the previous props. This is
because your component constructor function is called with the
updated props. Similarly, if you wish to detect local state transitions, you should use
om.core/get-render-state to get the previous local state.
Note:: You cannot update local component state in this method. If you wish to change local state in response to prop changes use IWillReceiveProps.
(defprotocol IDidUpdate
(did-update [this prev-props prev-state]))Called when React has rendered the component into the
DOM. prev-props is the previous application state associated with
this component. prev-state is the previous component local state, it
is always a map.
(defprotocol IRender
(render [this]))Called on all changes to application state or component local state. Must return an Om component, a React component, or some value that React knows how to render.
If you implement om.core/IRender you should not implement
om.core/IRenderState.
(defprotocol IRenderState
(render-state [this state]))The only difference between om.core/IRender and
om.core/IRenderState is that IRenderState implementations get the
state as an argument. state is always a map, you can use destructuring.
If you implement om.core/IRenderState you should not implement
om.core/IRender.
(defprotocol IDisplayName
(display-name [this]))Return a string name to be used for debugging. The Chrome React Developer Tools extension uses this to name the components.
(defprotocol IWillUnmount
(will-unmount [this]))Called immediately before a component is unmounted from the DOM.
Perform any necessary cleanup in this method, such as invalidating timers or cleaning up any DOM elements that were created in om.core/IDidMount.
(defn get-props [owner]
...)owner is the backing Om component. om.core/get-props returns the value associated with the component. This value is associated with the component by om.core/build (and is referred to simply as x in the documentation for build). The value is usually a cursor, although any value is actually permitted. A cursor is a piece of the application state that knows how to update itself.
(defn get-state
([owner] ...)
([owner korks] ...))owner is the backing Om component. korks is a key or sequence of
keys. Will return the specified piece of component local state. Will
always return pending state.
(defn get-shared
([owner] ...)
([owner korks] ...))owner is the backing Om component. korks is a key or sequence of
keys. It will return data that is shared across the entire render tree.
You can set global shared data with om.core/root.
(defn root
([f value options] ...))f is a function returning an instance of IRender or IRenderState.
f takes two arguments, a root cursor on the application state and
the backing Om component for the root.
value is either a tree of
associative ClojureScript data structures or an atom wrapping a tree
of associative ClojureScript data structures.
options is a map containing any key allowed to om.core/build.
Additionally the following keys are allowed/required:
-
:target(required) -
:shared(optional) in order to provide global services -
:tx-listena function that will listen in on transactions, should take 2 arguments:- a map containing the path, old and new state at path, old and new global state, and transaction tag if provided (
:path,:old-value,:new-value,:old-state,:new-stateand:tag). - the root cursor.
- a map containing the path, old and new state at path, old and new global state, and transaction tag if provided (
-
:pathto specify the path of the cursor into app-state (see #72) -
:instrumenta function of three arguments that if provided will intercept all calls toom.core/build. The function arguments correspond exactly to the three argument arity ofom.core/build
om.core/root is idempotent. You may safely call it multiple
times. Only one Om render loop is ever allowed on a particular DOM
target.
(om.core/root
(fn [app-state owner]
(reify
om.core/IRender
(render [_]
(dom/h1 nil (:text app-state)))))
{:text "Hello world!"}
{:target (. js/document getElementById "my-app")}) (defn build
([f x] ...)
([f x m] ...))Constructs an Om component. f must be a function that returns an
instance of om.core/IRender or om.core/IRenderState. f must take
two arguments - a value and the backing Om component usually referred
to as the owner. f can take a third argument if :opts is specified
in m. The component is identified by the function f. Changing f
to a different function will construct a new component, while changing
the return value will not change component. x can be any value. m
is an optional map of options.
Only the following keys are allowed in m.
:key - a keyword that will be used to lookup a value in x to
be used as a React key.
:key-fn - a function that will be applied to x to be used as a
React key.
:react-key - a value to use as a React key.
:fn - a function to apply to x before invoking f.
:init-state - a map of initial state to set on the component (state from IInitState is merged onto it).
:state - a map of state to merge into the component.
:opts - a map of side information.
(defn build*
([f x] ...)
([f x m] ...))Identical to om.core/build except cannot be intercepted by the
:instrument argument provided to om.core/root. Needed to avoid
infinite loops in components constructed via :instrument.
(defn build-all
([f xs] ...)
([f xs m] ...)Conceptually the same as om.core/build, the only difference is that
it returns a sequence of Om components. xs is a sequence of
values. f and m are the same as om.core/build. To avoid
the warning "Each child in an array should have a unique “key” prop",
add either a :key or :key-fn to m.
(defn transact!
([cursor f] ...)
([cursor korks f] ...)
([cursor korks f tag]) ...)The primary way to transition application state. cursor is an Om
cursor into the application state. f is a function that will receive
the specified piece of application state. korks is an optional
key or sequence of keys to access in the cursor. tag is optional
information to tag the transaction. tag should be either a keyword
or a vector whose first element is a keyword.
(transact! cursor :text (fn [_] "Changed this!"))(defn update!
([cursor v] ...)
([cursor korks v] ...)
([cursor korks v tag] ...))Similar to om.core/transact! but just sets a cursor to a new value,
analagous to reset! for atoms.
(update! cursor [:text] "Changed this!")(defn path
([cursor] ...))(defn state
([cursor] ...))(defn value
([cursor] ...))(defn get-node
([owner ref] ...)
([owner] ...))owner is the backing Om component. ref is a JavaScript String that
references a DOM node. This functionality is identical to the
ReactComponent.getDOMNode in React.
(defn set-state!
([owner v] ...)
([owner korks v] ...))Sets component local state. owner is the backing Om
component. korks is an optional key or sequence of keys. v is the value to
set. Will trigger an Om re-render.
(defn update-state!
([owner f] ...)
([owner korks f] ...))Takes a pure owning component, an optional sequential list of keys and a function to transition the state of the component. Conceptually analogous to React setState. Will schedule an Om re-render.
(defn refresh! [owner]
...)Utility to re-render an owner. Delegates to update-state!.
(defn get-render-state
([owner] ...)
([owner korks] ...))Returns rendered component local state. owner is the backing Om
component. korks is an optional key or sequences of keys. Similar to
om.core/get-state except always returns the rendered state. Useful
for detecting state transitions.
(defn detach-root [target]
...)Given a DOM target, remove its render loop if one exists.
(defn root-cursor [atom]
...)Given an application state atom, return a root cursor for it.
(defn ref-cursor [cursor]
...)Given a cursor, return a reference cursor that inherits all of the
properties and methods of the cursor. Reference cursors may be
observed via om.core/observe.
(defn observe [owner ref]
...)Given a component and a reference cursor, have the component observe the reference cursor for any data changes. Evaluates to the given reference cursor.
(defmacro component [& body]
...)Sugar over reify for quickly putting together components that
only need to implement om.core/IRender and don't need access to
the owner argument.
The dom functions map directly to the DOM api presented by React. For
example React.DOM.div becomes om.dom/div. The arguments are exactly
the same as React, the first argument is props, all subsequent
arguments are children.
For a list of supported props see React's supported DOM attributes and React's special attributes. As an example of the special attributes, the following code will create a div component that contains raw HTML:
(om.dom/div #js {:dangerouslySetInnerHTML #js {:__html "<b>Bold!</b>"}}
nil)Be careful! The attribute is well-named: this is potentially dangerous and should be used with caution.
(defn render-to-str [c]
...)Equivalent to React.renderComponentToString. For example:
(dom/render-to-str (om/build some-widget data))