Add import-react macro

This commit is contained in:
Dan Holmsand 2014-04-09 16:50:15 +02:00
parent 429ed50fab
commit 41a687faa7
7 changed files with 55 additions and 25 deletions

View File

@ -1,6 +1,6 @@
(ns demo
(:require [reagent.core :as reagent :refer [atom]]
[reagent.interop :refer-macros [.' .! fvar]]
[reagent.interop :as i :refer-macros [.' .! fvar]]
[clojure.string :as string]
[reagentdemo.page :as page :refer [page-map page link prefix]]
[reagentdemo.common :as common :refer [demo-component]]
@ -8,6 +8,8 @@
[reagentdemo.news :as news]
[reagent.debug :refer-macros [dbg println]]))
(i/import-react)
(swap! page-map assoc
"index.html" (fvar intro/main)
"news/index.html" (fvar news/main))

View File

@ -13,7 +13,6 @@
{:client {:compiler
{:optimizations :advanced
:elide-asserts true
:preamble ^:replace ["reagent/react.min.js"]
:pretty-print false}}}}}
:test {:cljsbuild
{:builds
@ -37,7 +36,6 @@
"examples/geometry/src"]
:notify-command ["node" "./bin/gen-site.js"]
:compiler
{:preamble ["reagent/react.js"]
:output-dir "target/client"
{:output-dir "target/client"
:output-to "target/cljs-client.js"
:pretty-print true}}}})

View File

@ -9,8 +9,6 @@
[reagent.debug :refer-macros [dbg prn]]
[reagent.interop :refer-macros [.' .!]]))
(def React util/React)
(def is-client util/is-client)
(defn as-component
@ -40,7 +38,7 @@ Returns the mounted component instance."
(defn render-component-to-string
"Turns a component into an HTML string."
([component]
(.' React renderComponentToString (as-component component))))
(.' js/React renderComponentToString (as-component component))))
(defn ^:export force-update-all []
(util/force-update-all))

View File

@ -1,6 +1,6 @@
(ns reagent.impl.component
(:require [reagent.impl.util :as util :refer [React]]
(:require [reagent.impl.util :as util]
[reagent.impl.batching :as batch]
[reagent.ratom :as ratom]
[reagent.interop :refer-macros [.' .!]]
@ -183,7 +183,7 @@
(assert (map? body))
(let [spec (cljsify body)
_ (.! spec :asComponent (dont-bind as-component))
res (.' React createClass spec)
res (.' js/React createClass spec)
f (fn [& args]
(as-component (apply vector res args)))]
(util/cache-react-class f res)

View File

@ -1,20 +1,19 @@
(ns reagent.impl.template
(:require [clojure.string :as string]
[reagent.impl.util :as util :refer [is-client React]]
[reagent.impl.util :as util :refer [is-client]]
[reagent.impl.component :as comp]
[reagent.impl.batching :as batch]
[reagent.ratom :as ratom]
[reagent.interop :refer-macros [.' .!]]
[reagent.debug :refer-macros [dbg prn println log dev?]]))
;; From Weavejester's Hiccup, via pump:
(def ^{:doc "Regular expression that parses a CSS-style id and class
from a tag name."}
re-tag #"([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?")
(def DOM (.' React :DOM))
(def attr-aliases {:class "className"
:for "htmlFor"
:charset "charSet"})
@ -117,8 +116,10 @@
(.! :value nil)
(.! :onChange #(input-handle-change this on-change %))))))
(def input-components #{(.' DOM :input)
(.' DOM :textarea)})
(defn input-component? [x]
(let [DOM (.' js/React :DOM)]
(or (identical? x (.' DOM :input))
(identical? x (.' DOM :textarea)))))
;;; Wrapping of native components
@ -151,7 +152,7 @@
(.! :componentWillUnmount #(this-as c (batch/dispose c)))))
(defn wrap-component [comp extras name]
(let [input? (input-components comp)
(let [input? (input-component? comp)
input-setup (if input? input-render-setup)
spec #js{:render
#(this-as C (wrapped-render C comp extras input-setup))
@ -160,14 +161,14 @@
:displayName (or name "ComponentWrapper")}]
(when input?
(add-input-methods spec))
(.' React createClass spec)))
(.' js/React createClass spec)))
;;; Conversion from Hiccup forms
(defn parse-tag [hiccup-tag]
(let [[tag id class] (->> hiccup-tag name (re-matches re-tag) next)
comp (aget DOM tag)
comp (aget (.' js/React :DOM) tag)
class' (when class
(string/replace class #"\." " "))]
(assert comp (str "Unknown tag: '" hiccup-tag "'"))
@ -197,7 +198,7 @@
(let [cached-class (util/cached-react-class tag)]
(if-not (nil? cached-class)
cached-class
(if (.' React isValidClass tag)
(if (.' js/React isValidClass tag)
(util/cache-react-class tag (wrap-component tag nil nil))
(fn-to-class tag)))))))

View File

@ -6,8 +6,6 @@
(def is-client (and (exists? js/window)
(-> js/window (.' :document) nil? not)))
(def React js/React)
;;; Props accessors
(defn extract-props [v]
@ -128,11 +126,11 @@
(defn re-render-component [comp container]
(try
(.' React renderComponent (comp) container)
(.' js/React renderComponent (comp) container)
(catch js/Object e
(do
(try
(.' React unmountComponentAtNode container)
(.' js/React unmountComponentAtNode container)
(catch js/Object e
(log e)))
(when-let [n (get-react-node container)]
@ -141,7 +139,7 @@
(throw e)))))
(defn render-component [comp container callback]
(.' React renderComponent (comp) container
(.' js/React renderComponent (comp) container
(fn []
(let [id (get-root-id container)]
(when-not (nil? id)
@ -154,7 +152,7 @@
(let [id (get-root-id container)]
(when-not (nil? id)
(swap! roots dissoc id)))
(.' React unmountComponentAtNode container))
(.' js/React unmountComponentAtNode container))
(defn force-update-all []
(binding [*always-update* true]

View File

@ -1,5 +1,6 @@
(ns reagent.interop
(:require [clojure.string :as string :refer [join]]))
(:require [clojure.string :as string :refer [join]]
[clojure.java.io :as io]))
(defn- js-call [f args]
(let [argstr (->> (repeat (count args) "~{}")
@ -48,6 +49,38 @@
(assert field (str "Field name must start with - in " field))
`(aset ~object ~@names ~value)))
(def react-import-ns (atom nil))
(defmacro import-react
[]
"Import React.js.
This can be used instead of adding :preamble in project.clj
(or adding react.js in a script tag). This may be more convenient when
using :optimizations :none, since that doesn't take :preamble into account.
Imports minimized version of React if :elide-asserts is true."
(if-not (or (nil? @react-import-ns)
(= *ns* @react-import-ns))
;; React was already imported in another namespace; so we avoid
;; duplicate imports.
true
(let [srcfile (if *assert* "reagent/react.js"
"reagent/react.min.js")
src (slurp (io/resource srcfile))]
(if (nil? @react-import-ns)
(reset! react-import-ns *ns*))
`(js/eval ~(str "if (typeof React != 'undefined' &&
typeof console != 'undefined') {
console.log('WARNING: React is already defined');
}"
src "; \n"
"console.log('importing');"
"if (typeof module != 'undefined' &&
typeof global != 'undefined' &&
module.exports && module.exports.DOM) {
global.React = module.exports;
} \n
//@ sourceURL=" srcfile "\n")))))
(defmacro fvar
[f]