diff --git a/CHANGELOG.md b/CHANGELOG.md index c9bfb57..6bcd676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## Next + +- Removed deprecated namespaces/function/macros: + - Removed `reagent.interop` namespace (macros `$`, `$!`, `unchecked-aget` and `unchecked-aset`) +- Deprecated functions: + - `reagent.core/component-path` (Reason: implementation depends on internal React + details and using just Component `displayName` achieves nearly the same) +- All DOM related functions (notably `render` and `dom-node`) have been removed +from `reagent.core` namespace and are now only available in `reagent.dom` namespace. +This is to make non-DOM environments (React-native) first class targets with Reagent, +as requiring `react-dom` always causes problems in such environments. + ## 0.9.1 (2020-01-15) Removed broken untracked files from the package. diff --git a/demo/reagentdemo/intro.cljs b/demo/reagentdemo/intro.cljs index 1829141..2aed198 100644 --- a/demo/reagentdemo/intro.cljs +++ b/demo/reagentdemo/intro.cljs @@ -1,5 +1,6 @@ (ns reagentdemo.intro (:require [reagent.core :as r] + [reagent.dom :as rdom] [reagentdemo.syntax :as s] [reagentdemo.common :as common :refer [demo-component]] [simpleexample.core :as simple] @@ -62,7 +63,8 @@ "Seconds Elapsed: " @seconds-elapsed]))) (defn render-simple [] - (r/render [simple-component] + (rdom/render + [simple-component] (.-body js/document))) (def bmi-data (r/atom {:height 180 :weight 80})) @@ -222,7 +224,7 @@ [:p "Reagent supports most of React’s API, but there is really only one entry-point that is necessary for most applications: " - [:code "reagent.core/render"] "."] + [:code "reagent.dom/render"] "."] [:p "It takes two arguments: a component, and a DOM node. For example, splashing the very first example all over the page would diff --git a/demo/sitetools/core.cljs b/demo/sitetools/core.cljs index 05264d7..42e05bc 100644 --- a/demo/sitetools/core.cljs +++ b/demo/sitetools/core.cljs @@ -1,7 +1,8 @@ (ns sitetools.core (:require [clojure.string :as string] [goog.events :as evt] - [reagent.core :as r]) + [reagent.core :as r] + [reagent.dom :as rdom]) (:import goog.History [goog.history Html5History EventType])) @@ -110,4 +111,4 @@ conf (swap! config merge page-conf) {:keys [page-path body main-div]} conf] (init-history page-path) - (r/render body (js/document.getElementById main-div))))) + (rdom/render body (js/document.getElementById main-div))))) diff --git a/doc/InteropWithReact.md b/doc/InteropWithReact.md index 99eacf9..e1e1d70 100644 --- a/doc/InteropWithReact.md +++ b/doc/InteropWithReact.md @@ -33,11 +33,11 @@ As an example, here are four ways to create the same element: "world")]]) (defn mount-root [] - (reagent/render [integration] + (rdom/render [integration] (.getElementById js/document "app"))) ``` -This works because `reagent/render` itself expects (1) a React element or (2) a +This works because `reagent.dom/render` itself expects (1) a React element or (2) a Hiccup form. If passed an element, it just uses it. If passed a Hiccup, it creats a (cached) React component and then creates an element from that component. @@ -45,7 +45,7 @@ component. ## Creating React Elements from Hiccup forms The `reagent.core/as-element` function creates a React element from a Hiccup -form. In the previous section, we discussed how `reagent/render` expects either +form. In the previous section, we discussed how `reagent.dom/render` expects either (1) a Hiccup form or (2) a React Element. If it encounters a Hiccup form, it calls `as-element` on it. When you have a React component that wraps children, you can pass Hiccup forms to it wrapped in `as-element`. diff --git a/doc/ManagingState.md b/doc/ManagingState.md index ca68fdb..8579464 100644 --- a/doc/ManagingState.md +++ b/doc/ManagingState.md @@ -1,6 +1,6 @@ # Managing state: atoms, cursors, Reactions, and tracking -Although it is possible to update reagent components by remounting the entire component tree with `react.core/render`, Reagent comes with a sophisticated state management library based on `reagent.core/atom`, which allows components to track application state and update only when needed. Reagent also provides cursors, which are like ratoms but can be constructed from portions of one or more other ratoms to limit or expand which ratoms a component watches. Finally, Reagent provides a set of tracking primitives called reactions and a set of utility functions to build more customized state management. +Although it is possible to update reagent components by remounting the entire component tree with `reagent.dom/render`, Reagent comes with a sophisticated state management library based on `reagent.core/atom`, which allows components to track application state and update only when needed. Reagent also provides cursors, which are like ratoms but can be constructed from portions of one or more other ratoms to limit or expand which ratoms a component watches. Finally, Reagent provides a set of tracking primitives called reactions and a set of utility functions to build more customized state management. **TODO is this right?** @@ -133,8 +133,8 @@ Cursors are created with `reagent/cursor`, which takes a ratom and a keypath (li [:div @bar-cursor]) (defn mount-root [] - (reagent/render [:div [quux-component] [bar-component]] - (.getElementById js/document "app")) + (rdom/render [:div [quux-component] [bar-component]] + (.getElementById js/document "app")) (js/setTimeout (fn [] (swap! state assoc :baz "NEW BAZ")) 1000) (js/setTimeout (fn [] (swap! state assoc-in [:foo :bar] "NEW BAR")) 2000)) diff --git a/doc/ReactFeatures.md b/doc/ReactFeatures.md index cf81caa..abdf88b 100644 --- a/doc/ReactFeatures.md +++ b/doc/ReactFeatures.md @@ -37,11 +37,12 @@ Reagent syntax follows [React Fragment short syntax](https://reactjs.org/docs/fr (def Provider (.-Provider my-context)) (def Consumer (.-Consumer my-context)) -(r/render [:> Provider {:value "bar"} - [:> Consumer {} - (fn [v] - (r/as-element [:div "Context: " v]))]] - container) +(rdom/render + [:> Provider {:value "bar"} + [:> Consumer {} + (fn [v] + (r/as-element [:div "Context: " v]))]] + container) ``` Alternatively you can use the [static contextType property](https://reactjs.org/docs/context.html#classcontexttype) @@ -64,9 +65,10 @@ Alternatively you can use the [static contextType property](https://reactjs.org/ ;; (fn [] ;; [:p (.-context (reagent.core/current-component))])) -(r/render [:> Provider {:value "bar"} - [show-context]] - container) +(rdom/render + [:> Provider {:value "bar"} + [show-context]] + container) ``` Tests contain example of using old React lifecycle Context API (`context-wrapper` function): diff --git a/doc/UsingHiccupToDescribeHTML.md b/doc/UsingHiccupToDescribeHTML.md index 9c9211c..68e77dd 100644 --- a/doc/UsingHiccupToDescribeHTML.md +++ b/doc/UsingHiccupToDescribeHTML.md @@ -119,7 +119,7 @@ The primary entrypoint to the reagent library is `reagent.core/render`. (:require [reagent.core :as r])) (defn render-simple [] - (r/render [:div [:p "Hello world!"]] + (rdom/render [:div [:p "Hello world!"]] (.-body js/document))) ``` @@ -137,5 +137,5 @@ If it's a symbol, then reagent will evaluate a function by that name. Reagent ex 1. A Hiccup vector. Reagent creates a React component with the function as its render method and uses the Hiccup vector for the initial render. 2. A ClojureScript function. Reagent will then create a React component with this inner function as the render method and will then call the inner function for the initial render. -3. A React component. Reagent will render this using React.createElement. Note, this could be a result of calling (React.core/create-class) or it could be a React component you have imported from a JavaScript library. +3. A React component. Reagent will render this using React.createElement. Note, this could be a result of calling `reagent.core/create-class` or it could be a React component you have imported from a JavaScript library. diff --git a/doc/examples/smooth-ui.md b/doc/examples/smooth-ui.md index d5c68e2..7d53275 100644 --- a/doc/examples/smooth-ui.md +++ b/doc/examples/smooth-ui.md @@ -16,5 +16,5 @@ it's workaround logic to control input value and cursor position: ; (.. system -meta -props) [:input (dissoc props :__scTheme :theme :control :size :valid)]))) -(r/render [:> Input {:as r-input ...}] container) +(rdom/render [:> Input {:as r-input ...}] container) ``` diff --git a/examples/geometry/src/geometry/core.cljs b/examples/geometry/src/geometry/core.cljs index 27b9baa..8fcccab 100644 --- a/examples/geometry/src/geometry/core.cljs +++ b/examples/geometry/src/geometry/core.cljs @@ -1,5 +1,6 @@ (ns geometry.core (:require [reagent.core :as r] + [reagent.dom :as rdom] [geometry.components :as c] [geometry.geometry :as g])) @@ -33,7 +34,7 @@ (defn get-bcr [svg-root] (-> svg-root - r/dom-node + rdom/dom-node .getBoundingClientRect)) (defn move-point [svg-root p] @@ -85,5 +86,4 @@ (.getElementById js/document id)) (defn ^:export run [] - (r/render [main] - (by-id "app"))) + (rdom/render [main] (by-id "app"))) diff --git a/examples/material-ui/src/example/core.cljs b/examples/material-ui/src/example/core.cljs index 064a751..5d64da5 100644 --- a/examples/material-ui/src/example/core.cljs +++ b/examples/material-ui/src/example/core.cljs @@ -1,5 +1,6 @@ (ns example.core (:require [reagent.core :as r] + [reagent.dom :as rdom] ;; Scoped names require Cljs 1.10.439 ["@material-ui/core" :as mui] ["@material-ui/core/styles" :refer [createMuiTheme withStyles]] @@ -173,6 +174,6 @@ [:> (with-custom-styles (r/reactify-component form))]]]]]) (defn start [] - (r/render [main] (js/document.getElementById "app"))) + (rdom/render [main] (js/document.getElementById "app"))) (start) diff --git a/examples/react-sortable-hoc/src/example/core.cljs b/examples/react-sortable-hoc/src/example/core.cljs index 91da1ab..842ec8f 100644 --- a/examples/react-sortable-hoc/src/example/core.cljs +++ b/examples/react-sortable-hoc/src/example/core.cljs @@ -1,5 +1,6 @@ (ns example.core (:require [reagent.core :as r] + [reagent.dom :as rdom] ;; FIXME: add global-exports support [cljsjs.react-sortable-hoc] [goog.object :as gobj])) @@ -70,6 +71,6 @@ [sortable-component]) (defn start [] - (r/render [main] (js/document.getElementById "app"))) + (rdom/render [main] (js/document.getElementById "app"))) (start) diff --git a/examples/simple/src/simpleexample/core.cljs b/examples/simple/src/simpleexample/core.cljs index f90333c..24d5f34 100644 --- a/examples/simple/src/simpleexample/core.cljs +++ b/examples/simple/src/simpleexample/core.cljs @@ -1,5 +1,6 @@ (ns simpleexample.core - (:require [reagent.core :as r])) + (:require [reagent.core :as r] + [reagent.dom :as rdom])) (defonce timer (r/atom (js/Date.))) @@ -31,5 +32,4 @@ [color-input]]) (defn ^:export run [] - (r/render [simple-example] - (js/document.getElementById "app"))) + (rdom/render [simple-example] (js/document.getElementById "app"))) diff --git a/examples/todomvc/src/todomvc/core.cljs b/examples/todomvc/src/todomvc/core.cljs index 93ed17d..87de365 100644 --- a/examples/todomvc/src/todomvc/core.cljs +++ b/examples/todomvc/src/todomvc/core.cljs @@ -1,5 +1,6 @@ (ns todomvc.core - (:require [reagent.core :as r])) + (:require [reagent.core :as r] + [reagent.dom :as rdom])) (defonce todos (r/atom (sorted-map))) @@ -42,7 +43,7 @@ nil)}]))) (def todo-edit (with-meta todo-input - {:component-did-mount #(.focus (r/dom-node %))})) + {:component-did-mount #(.focus (rdom/dom-node %))})) (defn todo-stats [{:keys [filt active done]}] (let [props-for (fn [name] @@ -105,5 +106,4 @@ [:p "Double-click to edit a todo"]]])))) (defn ^:export run [] - (r/render [todo-app] - (js/document.getElementById "app"))) + (rdom/render [todo-app] (js/document.getElementById "app"))) diff --git a/project.clj b/project.clj index 2de72d5..51f6378 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject reagent "0.10.0-SNAPSHOT" +(defproject reagent "1.0.0-SNAPSHOT" :url "http://github.com/reagent-project/reagent" :license {:name "MIT"} :description "A simple ClojureScript interface to React" diff --git a/src/reagent/core.cljs b/src/reagent/core.cljs index e898c13..ca983a0 100644 --- a/src/reagent/core.cljs +++ b/src/reagent/core.cljs @@ -9,8 +9,7 @@ [reagent.ratom :as ratom] [reagent.debug :as deb :refer-macros [assert-some assert-component assert-js-object assert-new-state - assert-callable]] - [reagent.dom :as dom])) + assert-callable]])) (def is-client util/is-client) @@ -64,43 +63,6 @@ (assert-some c "Component") (comp/reactify-component c)) -(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] - (dom/render comp container)) - ([comp container callback] - (dom/render comp container callback))) - -(defn unmount-component-at-node - "Remove a component from the given DOM node." - [container] - (dom/unmount-component-at-node container)) - -;; For backward compatibility -(def ^{:deprecated "0.10.0"} as-component as-element) -(def ^{:deprecated "0.10.0"} render-component render) - -(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!) - (dom/force-update-all) - (batch/flush-after-render)) - (defn create-class "Creates JS class based on provided Clojure map, for example: @@ -210,11 +172,6 @@ (assert-component this) (comp/get-argv this)) -(defn dom-node - "Returns the root DOM node of a mounted component." - [this] - (dom/dom-node this)) - (defn class-names "Function which normalizes and combines class values to a string @@ -238,7 +195,7 @@ ([defaults props & others] (apply util/merge-props defaults props others))) (defn flush - "Render dirty components immediately to the DOM. + "Render dirty components immediately. Note that this may not work in event handlers, since React.js does batching of updates there." @@ -393,6 +350,6 @@ "Try to return the path of component c as a string. Maybe useful for debugging and error reporting, but may break with future versions of React (and return nil)." - {:deprecated "0.10.0"} + {:deprecated "1.0.0"} [c] (comp/component-path c)) diff --git a/src/reagent/dom.cljs b/src/reagent/dom.cljs index 370442d..a9ebc27 100644 --- a/src/reagent/dom.cljs +++ b/src/reagent/dom.cljs @@ -26,7 +26,8 @@ (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. + 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. @@ -39,7 +40,9 @@ (tmpl/as-element (if (fn? comp) (comp) comp)))] (render-comp f container callback)))) -(defn unmount-component-at-node [container] +(defn unmount-component-at-node + "Remove a component from the given DOM node." + [container] (unmount-comp container)) (defn dom-node @@ -63,4 +66,4 @@ (ratom/flush!) (doseq [v (vals @roots)] (apply re-render-component v)) - "Updated") + (batch/flush-after-render)) diff --git a/test-environments/browser-cljsjs-prod/test.sh b/test-environments/browser-cljsjs-prod/test.sh index ff88d38..2f5f7e0 100755 --- a/test-environments/browser-cljsjs-prod/test.sh +++ b/test-environments/browser-cljsjs-prod/test.sh @@ -1,5 +1,6 @@ #!/bin/bash set -ex -lein do clean, doo chrome-headless prod-test once +rm -rf target/cljsbuild/prod-test/ +lein doo chrome-headless prod-test once test -f target/cljsbuild/prod-test/main.js node_modules/.bin/gzip-size target/cljsbuild/prod-test/main.js diff --git a/test-environments/browser-cljsjs/test.sh b/test-environments/browser-cljsjs/test.sh index 247b957..16e072c 100755 --- a/test-environments/browser-cljsjs/test.sh +++ b/test-environments/browser-cljsjs/test.sh @@ -1,4 +1,5 @@ #!/bin/bash set -ex -lein do clean, doo chrome-headless test once +rm -rf target/cljsbuild/test/ +lein doo chrome-headless test once test -f target/cljsbuild/test/out/cljsjs/react/development/react.inc.js diff --git a/test-environments/browser-npm-prod/test.sh b/test-environments/browser-npm-prod/test.sh index 81a2b87..ee63c14 100755 --- a/test-environments/browser-npm-prod/test.sh +++ b/test-environments/browser-npm-prod/test.sh @@ -2,6 +2,7 @@ set -ex -lein do clean, doo chrome-headless prod-test-npm once +rm -rf target/cljsbuild/prod-test-npm/ +lein doo chrome-headless prod-test-npm once test -f target/cljsbuild/prod-test-npm/main.js node_modules/.bin/gzip-size target/cljsbuild/prod-test-npm/main.js diff --git a/test-environments/browser-npm/test.sh b/test-environments/browser-npm/test.sh index ba2b92d..1f093ff 100755 --- a/test-environments/browser-npm/test.sh +++ b/test-environments/browser-npm/test.sh @@ -1,4 +1,5 @@ #!/bin/bash set -ex -lein do clean, doo chrome-headless test-npm once +rm -rf target/cljsbuild/test-npm/ +lein doo chrome-headless test-npm once test -f target/cljsbuild/test-npm/out/node_modules/react/index.js diff --git a/test-environments/node-cljsjs/test.sh b/test-environments/node-cljsjs/test.sh index 7bdb897..153022f 100755 --- a/test-environments/node-cljsjs/test.sh +++ b/test-environments/node-cljsjs/test.sh @@ -1,4 +1,5 @@ #!/bin/bash set -ex -lein do clean, doo node node-test once +rm -rf target/cljsbuild/node-test/ +lein doo node node-test once test -f target/cljsbuild/node-test/out/cljsjs/react/development/react.inc.js diff --git a/test-environments/node-npm/test.sh b/test-environments/node-npm/test.sh index ea1070e..2fc9888 100755 --- a/test-environments/node-npm/test.sh +++ b/test-environments/node-npm/test.sh @@ -1,5 +1,6 @@ #!/bin/bash set -ex -lein do clean, doo node node-test-npm once +rm -rf target/cljsbuild/node-test-npm/ +lein doo node node-test-npm once test ! -f target/cljsbuild/node-test-npm/out/node_modules/react/index.js grep "reagent.impl.template.node\$module\$react = require('react')" target/cljsbuild/node-test-npm/out/reagent/impl/template.js diff --git a/test-environments/shadow-cljs-prod/test.sh b/test-environments/shadow-cljs-prod/test.sh index a04b92c..e9db2a2 100755 --- a/test-environments/shadow-cljs-prod/test.sh +++ b/test-environments/shadow-cljs-prod/test.sh @@ -1,5 +1,6 @@ #!/bin/bash set -ex +rm -rf target/shadow-cljs/ npx shadow-cljs release test test -f target/shadow-cljs/resources/public/js/karma.js karma start test-environments/shadow-cljs-prod/karma.conf.js --single-run diff --git a/test/reagenttest/testreagent.cljs b/test/reagenttest/testreagent.cljs index 1cd1493..22faea8 100644 --- a/test/reagenttest/testreagent.cljs +++ b/test/reagenttest/testreagent.cljs @@ -4,6 +4,7 @@ [reagent.ratom :as rv :refer-macros [reaction]] [reagent.debug :as debug :refer-macros [dev?]] [reagent.core :as r] + [reagent.dom :as rdom] [reagent.dom.server :as server] [reagent.impl.component :as comp] [reagenttest.utils :as u :refer [with-mounted-component]] @@ -45,7 +46,7 @@ (is (= "div in really-simple" (.-innerText div))) (r/flush) (is (= 2 @ran)) - (r/force-update-all) + (rdom/force-update-all) (is (= 3 @ran)))) (is (= 3 @ran))))) @@ -187,7 +188,7 @@ (is (= "this is foobar" (.-innerText div))))) (is (= 2 @ran))))) -(deftest shoud-update-test +(deftest should-update-test (when r/is-client (let [parent-ran (r/atom 0) child-ran (r/atom 0) @@ -246,7 +247,7 @@ (r/flush) (is (= 7 @child-ran)) - (r/force-update-all) + (rdom/force-update-all) (is (= 8 @child-ran))))))) (deftest dirty-test @@ -1080,7 +1081,7 @@ [:div {:ref #(reset! ref %)} "foobar"]) :component-did-mount (fn [this] - (reset! node (r/dom-node this)))})] + (reset! node (rdom/dom-node this)))})] (with-mounted-component [comp] (fn [c div] (is (= "foobar" (.-innerHTML @ref))) diff --git a/test/reagenttest/utils.cljs b/test/reagenttest/utils.cljs index ed320e4..205cb3b 100644 --- a/test/reagenttest/utils.cljs +++ b/test/reagenttest/utils.cljs @@ -1,22 +1,23 @@ (ns reagenttest.utils - (:require [reagent.core :as r])) + (:require [reagent.core :as r] + [reagent.dom :as rdom])) (defn with-mounted-component [comp f] (when r/is-client (let [div (.createElement js/document "div")] (try - (let [c (r/render comp div)] + (let [c (rdom/render comp div)] (f c div)) (finally - (r/unmount-component-at-node div) + (rdom/unmount-component-at-node div) (r/flush)))))) (defn with-mounted-component-async [comp done f] (when r/is-client (let [div (.createElement js/document "div") - c (r/render comp div)] + c (rdom/render comp div)] (f c div (fn [] - (r/unmount-component-at-node div) + (rdom/unmount-component-at-node div) (r/flush) (done))))))