79 lines
2.6 KiB
Clojure
79 lines
2.6 KiB
Clojure
(ns reagent.dom
|
|
(:require [cljsjs.react.dom]
|
|
[reagent.impl.util :as util]
|
|
[reagent.impl.template :as tmpl]
|
|
[reagent.impl.batching :as batch]
|
|
[reagent.ratom :as ratom]
|
|
[reagent.debug :refer-macros [dbg]]
|
|
[reagent.interop :refer-macros [$ $!]]))
|
|
|
|
(defonce ^:private imported nil)
|
|
|
|
(defn module []
|
|
(cond
|
|
(some? imported) imported
|
|
(exists? js/ReactDOM) (set! imported js/ReactDOM)
|
|
(exists? js/require) (or (set! imported (js/require "react-dom"))
|
|
(throw (js/Error. "require('react-dom') failed")))
|
|
:else
|
|
(throw (js/Error. "js/ReactDOM is missing"))))
|
|
|
|
|
|
(defonce ^:private roots (atom {}))
|
|
|
|
(defn- unmount-comp [container]
|
|
(swap! roots dissoc container)
|
|
($ (module) unmountComponentAtNode container))
|
|
|
|
(defn- render-comp [comp container callback]
|
|
(binding [util/*always-update* true]
|
|
(->> ($ (module) render (comp) container
|
|
(fn []
|
|
(binding [util/*always-update* false]
|
|
(swap! roots assoc container [comp container])
|
|
(batch/flush-after-render)
|
|
(if (some? callback)
|
|
(callback))))))))
|
|
|
|
(defn- re-render-component [comp container]
|
|
(render-comp comp container nil))
|
|
|
|
(defn render
|
|
"Render a Reagent component into the DOM. The first argument may be
|
|
either a vector (using Reagent's Hiccup syntax), or a React element. The second argument should be a DOM node.
|
|
|
|
Optionally takes a callback that is called when the component is in place.
|
|
|
|
Returns the mounted component instance."
|
|
([comp container]
|
|
(render comp container nil))
|
|
([comp container callback]
|
|
(ratom/flush!)
|
|
(let [f (fn []
|
|
(tmpl/as-element (if (fn? comp) (comp) comp)))]
|
|
(render-comp f container callback))))
|
|
|
|
(defn unmount-component-at-node [container]
|
|
(unmount-comp container))
|
|
|
|
(defn dom-node
|
|
"Returns the root DOM node of a mounted component."
|
|
[this]
|
|
($ (module) findDOMNode this))
|
|
|
|
(defn force-update-all
|
|
"Force re-rendering of all mounted Reagent components. This is
|
|
probably only useful in a development environment, when you want to
|
|
update components in response to some dynamic changes to code.
|
|
|
|
Note that force-update-all may not update root components. This
|
|
happens if a component 'foo' is mounted with `(render [foo])` (since
|
|
functions are passed by value, and not by reference, in
|
|
ClojureScript). To get around this you'll have to introduce a layer
|
|
of indirection, for example by using `(render [#'foo])` instead."
|
|
[]
|
|
(ratom/flush!)
|
|
(doseq [v (vals @roots)]
|
|
(apply re-render-component v))
|
|
"Updated")
|