From 2f9e91d6971616eba5bf719a7118034c82093916 Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Tue, 13 Aug 2019 09:14:40 +0300 Subject: [PATCH 1/6] Add support for UNSAFE_ lifecycle methods & use for impl and tests --- package.json | 7 ++++-- project.clj | 6 ++--- src/deps.cljs | 4 ++-- src/reagent/impl/component.cljs | 37 +++++++++++++++++++++++++++---- src/reagent/impl/template.cljs | 4 ++-- src/reagent/impl/util.cljs | 10 ++++++++- test/reagent/impl/util_test.cljs | 14 ++++++++++++ test/reagenttest/testreagent.cljs | 12 +++++----- 8 files changed, 74 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 3451920..e252d8f 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,11 @@ "dependencies": { "@cljs-oss/module-deps": "1.1.1", "prop-types": "15.6.2", - "react": "16.8.6", - "react-dom": "16.8.6" + "react": "16.9.0", + "react-dom": "16.9.0" + }, + "scripts": { + "start": "lein figwheel client-npm" }, "devDependencies": { "gzip-size-cli": "3.0.0", diff --git a/project.clj b/project.clj index 2f69200..ba59ed8 100644 --- a/project.clj +++ b/project.clj @@ -7,9 +7,9 @@ ;; If :npm-deps enabled, these are used only for externs. ;; Without direct react dependency, other packages, ;; like react-leaflet might have closer dependency to a other version. - [cljsjs/react "16.8.6-0"] - [cljsjs/react-dom "16.8.6-0"] - [cljsjs/react-dom-server "16.8.6-0"]] + [cljsjs/react "16.9.0-0"] + [cljsjs/react-dom "16.9.0-0"] + [cljsjs/react-dom-server "16.9.0-0"]] :plugins [[lein-cljsbuild "1.1.7"] [lein-doo "0.1.11"] diff --git a/src/deps.cljs b/src/deps.cljs index 3c109f0..e949044 100644 --- a/src/deps.cljs +++ b/src/deps.cljs @@ -1,2 +1,2 @@ -{:npm-deps {"react" "16.8.6" - "react-dom" "16.8.6"}} +{:npm-deps {"react" "16.9.0" + "react-dom" "16.9.0"}} diff --git a/src/reagent/impl/component.cljs b/src/reagent/impl/component.cljs index 851ad05..916081e 100644 --- a/src/reagent/impl/component.cljs +++ b/src/reagent/impl/component.cljs @@ -167,10 +167,16 @@ (fn getInitialState [c] (reset! (state-atom c) (.call f c c))) + ;; Deprecated - warning in 16.9 will work through 17.x :componentWillReceiveProps (fn componentWillReceiveProps [nextprops] (this-as c (.call f c c (props-argv c nextprops)))) + ;; Deprecated - will work in 17.x + :UNSAFE_componentWillReceiveProps + (fn componentWillReceiveProps [nextprops] + (this-as c (.call f c c (props-argv c nextprops)))) + :shouldComponentUpdate (fn shouldComponentUpdate [nextprops nextstate] (or util/*always-update* @@ -188,14 +194,21 @@ noargv (.call f c c (get-argv c) (props-argv c nextprops)) :else (.call f c c old-argv new-argv)))))) + ;; Deprecated - warning in 16.9 will work through 17.x :componentWillUpdate (fn componentWillUpdate [nextprops] (this-as c (.call f c c (props-argv c nextprops)))) + ;; Deprecated - will work in 17.x + :UNSAFE_componentWillUpdate + (fn componentWillUpdate [nextprops] + (this-as c (.call f c c (props-argv c nextprops)))) + :componentDidUpdate (fn componentDidUpdate [oldprops] (this-as c (.call f c c (props-argv c oldprops)))) + ;; Deprecated - warning in 16.9 will work through 17.x :componentWillMount (fn componentWillMount [] (this-as c @@ -203,6 +216,14 @@ (when-not (nil? f) (.call f c c)))) + ;; Deprecated - will work in 17.x + :UNSAFE_componentWillMount + (fn componentWillMount [] + (this-as c + (set! (.-cljsMountOrder c) (batch/next-mount-count)) + (when-not (nil? f) + (.call f c c)))) + :componentDidMount (fn componentDidMount [] (this-as c (.call f c c))) @@ -230,18 +251,26 @@ ;; Though the value is nil here, the wrapper function will be ;; added to class to manage Reagent ratom lifecycle. (def obligatory {:shouldComponentUpdate nil - :componentWillMount nil + ;; Handled in add-oblifatory fn + ; :componentWillMount nil :componentWillUnmount nil}) -(def dash-to-camel (util/memoize-1 util/dash-to-camel)) +(def dash-to-method-name (util/memoize-1 util/dash-to-method-name)) (defn camelify-map-keys [fun-map] (reduce-kv (fn [m k v] - (assoc m (-> k dash-to-camel keyword) v)) + (assoc m (-> k dash-to-method-name keyword) v)) {} fun-map)) (defn add-obligatory [fun-map] - (merge obligatory fun-map)) + (merge obligatory + ;; If fun map contains the old name, without UNSAFE_ prefix, use that + ;; name, so user will get a warning. If no method use UNSAFE_ method + ;; for Reagent implementation. + (if (contains? fun-map :componentWillMount) + nil + {:UNSAFE_componentWillMount nil}) + fun-map)) (defn wrap-funs [fmap] (when (dev?) diff --git a/src/reagent/impl/template.cljs b/src/reagent/impl/template.cljs index 6fdf419..01b704a 100644 --- a/src/reagent/impl/template.cljs +++ b/src/reagent/impl/template.cljs @@ -46,7 +46,7 @@ (if (named? k) (if-some [k' (cache-get prop-name-cache (name k))] k' - (let [v (util/dash-to-camel k)] + (let [v (util/dash-to-prop-name k)] (gobj/set prop-name-cache (name k)) v)) k)) @@ -78,7 +78,7 @@ (if (named? k) (if-some [k' (cache-get custom-prop-name-cache (name k))] k' - (let [v (util/dash-to-camel k)] + (let [v (util/dash-to-prop-name k)] (gobj/set custom-prop-name-cache (name k) v) v)) k)) diff --git a/src/reagent/impl/util.cljs b/src/reagent/impl/util.cljs index a590c20..c055394 100644 --- a/src/reagent/impl/util.cljs +++ b/src/reagent/impl/util.cljs @@ -28,7 +28,7 @@ (string/upper-case s) (str (string/upper-case (subs s 0 1)) (subs s 1)))) -(defn dash-to-camel [dashed] +(defn dash-to-prop-name [dashed] (if (string? dashed) dashed (let [name-str (name dashed) @@ -37,6 +37,14 @@ name-str (apply str start (map capitalize parts)))))) +(defn dash-to-method-name [dashed] + (if (string? dashed) + dashed + (let [name-str (name dashed) + name-str (string/replace name-str #"(unsafe|UNSAFE)[-_]" "UNSAFE_") + [start & parts] (string/split name-str #"-")] + (apply str start (map capitalize parts))))) + (defn fun-name [f] (let [n (or (and (fn? f) (or (.-displayName f) diff --git a/test/reagent/impl/util_test.cljs b/test/reagent/impl/util_test.cljs index 311d4a3..3c312bf 100644 --- a/test/reagent/impl/util_test.cljs +++ b/test/reagent/impl/util_test.cljs @@ -19,6 +19,20 @@ (is (= "a b c d" (util/class-names "a" "b" nil ["c" "d"])))) +(deftest dash-to-prop-name-test + (is (= "tabIndex" (util/dash-to-prop-name :tab-index))) + (is (= "data-foo-bar" (util/dash-to-prop-name :data-foo-bar)))) + +(deftest dash-to-method-name-test + (is (= "componentDidMount" + (util/dash-to-method-name :component-did-mount))) + (is (= "componentDidMount" + (util/dash-to-method-name :componentDidMount))) + (is (= "UNSAFE_componentDidMount" + (util/dash-to-method-name :unsafe-component-did-mount))) + (is (= "UNSAFE_componentDidMount" + (util/dash-to-method-name :unsafe_componentDidMount)))) + ; (simple-benchmark [] ; (do (util/class-names "a" "b") ; (util/class-names nil "a") diff --git a/test/reagenttest/testreagent.cljs b/test/reagenttest/testreagent.cljs index 2209ff6..aaae185 100644 --- a/test/reagenttest/testreagent.cljs +++ b/test/reagenttest/testreagent.cljs @@ -740,7 +740,7 @@ (reset! t (first args)) (add-args :initial-state args) {:foo "bar"}) - :component-will-mount + :UNSAFE_component-will-mount (fn [& args] (this-as c (is (= c (first args)))) (add-args :will-mount args)) @@ -752,11 +752,11 @@ (fn [& args] (this-as c (is (= c (first args)))) (add-args :should-update args) true) - :component-will-receive-props + :UNSAFE_component-will-receive-props (fn [& args] (this-as c (is (= c (first args)))) (add-args :will-receive args)) - :component-will-update + :UNSAFE_component-will-update (fn [& args] (this-as c (is (= c (first args)))) (add-args :will-update args)) @@ -839,7 +839,7 @@ (reset! oldprops (-> args first r/props)) (add-args :initial-state args) {:foo "bar"}) - :component-will-mount + :UNSAFE_component-will-mount (fn [& args] (this-as c (is (= c (first args)))) (add-args :will-mount args)) @@ -851,14 +851,14 @@ (fn [& args] (this-as c (is (= c (first args)))) (add-args :should-update args) true) - :component-will-receive-props + :UNSAFE_component-will-receive-props (fn [& args] (reset! newprops (-> args second second)) (this-as c (is (= c (first args))) (add-args :will-receive (into [(dissoc (r/props c) :children)] (:children (r/props c)))))) - :component-will-update + :UNSAFE_component-will-update (fn [& args] (this-as c (is (= c (first args)))) (add-args :will-update args)) From 35ff5d33dd9dda6ac4103bb1bcb88580bdd12ddd Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Tue, 13 Aug 2019 09:32:11 +0300 Subject: [PATCH 2/6] Use DidMount for component mount order WillMount lifecycle method is being deprecated. DidMount can also be used to capture the mount order. WillMount is called first for top-most component and last for the children. DidMount is the reverse, first for children and last the top-most component. --- src/reagent/impl/batching.cljs | 11 ++++++++--- src/reagent/impl/component.cljs | 29 ++++++++++------------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/reagent/impl/batching.cljs b/src/reagent/impl/batching.cljs index 81385d8..5282c81 100644 --- a/src/reagent/impl/batching.cljs +++ b/src/reagent/impl/batching.cljs @@ -23,9 +23,14 @@ (.-msRequestAnimationFrame w) fake-raf)))) -(defn compare-mount-order [c1 c2] - (- (.-cljsMountOrder c1) - (.-cljsMountOrder c2))) +(defn compare-mount-order + [c1 c2] + ;; Mount order is now set in DidMount method. I.e. the + ;; top-most component is mounted last and gets largest + ;; number. This is reverse compared to WillMount where method + ;; for top component gets called first. + (- (.-cljsMountOrder c2) + (.-cljsMountOrder c1))) (defn run-queue [a] ;; sort components by mount order, to make sure parents diff --git a/src/reagent/impl/component.cljs b/src/reagent/impl/component.cljs index 916081e..9d3ee18 100644 --- a/src/reagent/impl/component.cljs +++ b/src/reagent/impl/component.cljs @@ -211,22 +211,21 @@ ;; Deprecated - warning in 16.9 will work through 17.x :componentWillMount (fn componentWillMount [] - (this-as c - (set! (.-cljsMountOrder c) (batch/next-mount-count)) - (when-not (nil? f) - (.call f c c)))) + (this-as c (.call f c c))) ;; Deprecated - will work in 17.x :UNSAFE_componentWillMount (fn componentWillMount [] - (this-as c - (set! (.-cljsMountOrder c) (batch/next-mount-count)) - (when-not (nil? f) - (.call f c c)))) + (this-as c (.call f c c))) :componentDidMount (fn componentDidMount [] - (this-as c (.call f c c))) + (this-as c + ;; This method is called after everything inside the + ;; has been mounted. This is reverse compared to WillMount. + (set! (.-cljsMountOrder c) (batch/next-mount-count)) + (when-not (nil? f) + (.call f c c)))) :componentWillUnmount (fn componentWillUnmount [] @@ -251,8 +250,7 @@ ;; Though the value is nil here, the wrapper function will be ;; added to class to manage Reagent ratom lifecycle. (def obligatory {:shouldComponentUpdate nil - ;; Handled in add-oblifatory fn - ; :componentWillMount nil + :componentDidMount nil :componentWillUnmount nil}) (def dash-to-method-name (util/memoize-1 util/dash-to-method-name)) @@ -263,14 +261,7 @@ {} fun-map)) (defn add-obligatory [fun-map] - (merge obligatory - ;; If fun map contains the old name, without UNSAFE_ prefix, use that - ;; name, so user will get a warning. If no method use UNSAFE_ method - ;; for Reagent implementation. - (if (contains? fun-map :componentWillMount) - nil - {:UNSAFE_componentWillMount nil}) - fun-map)) + (merge obligatory fun-map)) (defn wrap-funs [fmap] (when (dev?) From f91c97a70c663a720c93abe8c318583933fabd7d Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Tue, 13 Aug 2019 21:33:36 +0300 Subject: [PATCH 3/6] Update create-class docstring example --- src/reagent/core.cljs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/reagent/core.cljs b/src/reagent/core.cljs index 027957a..133217c 100644 --- a/src/reagent/core.cljs +++ b/src/reagent/core.cljs @@ -107,13 +107,14 @@ ```cljs {:get-initial-state (fn [this]) - :component-will-receive-props (fn [this new-argv]) + :UNSAFE_component-will-receive-props (fn [this new-argv]) :should-component-update (fn [this old-argv new-argv]) - :component-will-mount (fn [this]) + :UNSAFE_component-will-mount (fn [this]) :component-did-mount (fn [this]) - :component-will-update (fn [this new-argv]) + :UNSAFE_component-will-update (fn [this new-argv]) :component-did-update (fn [this old-argv]) :component-will-unmount (fn [this]) + :component-did-catch (fn [this error info]) :reagent-render (fn [args....])} ;; or :render (fn [this]) ``` From d4f14900da3f1d3ede1468e74c03c4fb5e88c783 Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Wed, 14 Aug 2019 10:35:59 +0300 Subject: [PATCH 4/6] Improved support for new lifecycle methods & better docs - separate getInitialState and constructor, they work differently - getDerivedStateFromProps and Error - getSnapshotBeforeUpdate - Improved docstring for create-class --- src/reagent/core.cljs | 31 +++++++++--- src/reagent/impl/component.cljs | 30 +++++++---- test/reagenttest/testreagent.cljs | 84 ++++++++++++++++++++++++++++++- 3 files changed, 127 insertions(+), 18 deletions(-) diff --git a/src/reagent/core.cljs b/src/reagent/core.cljs index 133217c..af96b5e 100644 --- a/src/reagent/core.cljs +++ b/src/reagent/core.cljs @@ -106,23 +106,40 @@ "Creates JS class based on provided Clojure map, for example: ```cljs - {:get-initial-state (fn [this]) - :UNSAFE_component-will-receive-props (fn [this new-argv]) + {;; Constructor + :constructor (fn [this props]) + :get-initial-state (fn [this]) + ;; Static methods + :get-derived-state-from-props (fn [props state] partial-state) + :get-derived-state-from-error (fn [error] partial-state) + ;; Methods + :get-snapshot-before-update (fn [this old-argv new-argv] snapshot) :should-component-update (fn [this old-argv new-argv]) - :UNSAFE_component-will-mount (fn [this]) :component-did-mount (fn [this]) - :UNSAFE_component-will-update (fn [this new-argv]) - :component-did-update (fn [this old-argv]) + :component-did-update (fn [this old-argv old-state snapshot]) :component-will-unmount (fn [this]) :component-did-catch (fn [this error info]) - :reagent-render (fn [args....])} ;; or :render (fn [this]) + :reagent-render (fn [args....]) + ;; Or alternatively: + :render (fn [this]) + ;; Deprecated methods: + :UNSAFE_component-will-receive-props (fn [this new-argv]) + :UNSAFE_component-will-update (fn [this new-argv new-state]) + :UNSAFE_component-will-mount (fn [this])} ``` Everything is optional, except either :reagent-render or :render. Map keys should use `React.Component` method names (https://reactjs.org/docs/react-component.html), and can be provided in snake-case or camelCase. - Constructor function is defined using key `:get-initial-state`. + + State can be initialized using constructor, which matches React.Component class, + or using getInitialState which matches old React createClass function and is + now implemented by Reagent for compatibility. + + State can usually be anything, e.g. Cljs object. But if using getDerivedState + methods, the state has to be plain JS object as React implementation uses + Object.assign to merge partial state into the current state. React built-in static methods or properties are automatically defined as statics." [spec] diff --git a/src/reagent/impl/component.cljs b/src/reagent/impl/component.cljs index 9d3ee18..c4b1552 100644 --- a/src/reagent/impl/component.cljs +++ b/src/reagent/impl/component.cljs @@ -162,11 +162,20 @@ :getDefaultProps (throw (js/Error. "getDefaultProps not supported")) + :getDerivedStateFromProps + (fn getDerivedStateFromProps [props state] + ;; Read props from Reagent argv + (.call f nil (if-some [a (.-argv props)] (extract-props a) props) state)) + ;; In ES6 React, this is now part of the constructor :getInitialState (fn getInitialState [c] (reset! (state-atom c) (.call f c c))) + :getSnapshotBeforeUpdate + (fn getSnapshotBeforeUpdate [oldprops oldstate] + (this-as c (.call f c c (props-argv c oldprops) oldstate))) + ;; Deprecated - warning in 16.9 will work through 17.x :componentWillReceiveProps (fn componentWillReceiveProps [nextprops] @@ -196,17 +205,17 @@ ;; Deprecated - warning in 16.9 will work through 17.x :componentWillUpdate - (fn componentWillUpdate [nextprops] - (this-as c (.call f c c (props-argv c nextprops)))) + (fn componentWillUpdate [nextprops nextstate] + (this-as c (.call f c c (props-argv c nextprops) nextstate))) ;; Deprecated - will work in 17.x :UNSAFE_componentWillUpdate - (fn componentWillUpdate [nextprops] - (this-as c (.call f c c (props-argv c nextprops)))) + (fn componentWillUpdate [nextprops nextstate] + (this-as c (.call f c c (props-argv c nextprops) nextstate))) :componentDidUpdate - (fn componentDidUpdate [oldprops] - (this-as c (.call f c c (props-argv c oldprops)))) + (fn componentDidUpdate [oldprops oldstate snapshot] + (this-as c (.call f c c (props-argv c oldprops) oldstate snapshot))) ;; Deprecated - warning in 16.9 will work through 17.x :componentWillMount @@ -317,17 +326,20 @@ [body] {:pre [(map? body)]} (let [body (cljsify body) - methods (map-to-js (apply dissoc body :displayName :getInitialState + methods (map-to-js (apply dissoc body :displayName :getInitialState :constructor :render :reagentRender built-in-static-method-names)) static-methods (map-to-js (select-keys body built-in-static-method-names)) display-name (:displayName body) - construct (:getInitialState body) + get-initial-state (:getInitialState body) + construct (:constructor body) cmp (fn [props context updater] (this-as this (.call react/Component this props context updater) (when construct - (construct this)) + (construct this props)) + (when get-initial-state + (set! (.-state this) (get-initial-state this))) this))] (gobj/extend (.-prototype cmp) (.-prototype react/Component) methods) diff --git a/test/reagenttest/testreagent.cljs b/test/reagenttest/testreagent.cljs index aaae185..eb9426a 100644 --- a/test/reagenttest/testreagent.cljs +++ b/test/reagenttest/testreagent.cljs @@ -7,6 +7,7 @@ [reagent.dom.server :as server] [reagent.impl.util :as util] [reagenttest.utils :as u :refer [with-mounted-component found-in]] + [clojure.string :as string] [goog.string :as gstr] [goog.object :as gobj] [prop-types :as prop-types])) @@ -794,11 +795,11 @@ (is (= (:should-update @res) {:at 6 :args [@t [@comp "a" "b"] [@comp "a" "c"]]})) (is (= (:will-update @res) - {:at 7 :args [@t [@comp "a" "c"]]})) + {:at 7 :args [@t [@comp "a" "c"] {:foo "bar"}]})) (is (= (:render @res) {:at 8 :args ["a" "c"]})) (is (= (:did-update @res) - {:at 9 :args [@t [@comp "a" "b"]]})))] + {:at 9 :args [@t [@comp "a" "b"] {:foo "bar"} nil]})))] (when isClient (with-mounted-component [c2] check) (is (= (:will-unmount @res) @@ -1266,3 +1267,82 @@ (is (not @error-thrown-after-updating-props)))))] (is (re-find #"Warning: Exception thrown while comparing argv's in shouldComponentUpdate:" (first (:warn e)))))))) + +(deftest get-derived-state-from-props-test + (when isClient + (let [prop (r/atom 0) + ;; Usually one can use Cljs object as React state. However, + ;; getDerivedStateFromProps implementation in React uses + ;; Object.assign to merge current state and partial state returned + ;; from the method, so the state has to be plain old object. + pure-component (r/create-class + {:constructor (fn [this] + (set! (.-state this) #js {})) + :get-derived-state-from-props (fn [props state] + ;; "Expensive" calculation based on the props + #js {:v (string/join " " (repeat (inc (:value props)) "foo"))}) + :render (fn [this] + (r/as-element [:p "Value " (.-v (.-state this))]))}) + component (fn [] + [pure-component {:value @prop}])] + (with-mounted-component [component] + (fn [c div] + (is (found-in #"Value foo" div)) + (swap! prop inc) + (r/flush) + (is (found-in #"Value foo foo" div))))))) + +(deftest get-derived-state-from-error-test + (when isClient + (let [prop (r/atom 0) + component (r/create-class + {:constructor (fn [this props] + (set! (.-state this) #js {:hasError false})) + :get-derived-state-from-error (fn [error] + #js {:hasError true}) + :component-did-catch (fn [this e info]) + :render (fn [this] + (js/console.log (r/children this)) + (r/as-element (if (.-hasError (.-state this)) + [:p "Error"] + (into [:<>] (r/children this)))))}) + bad-component (fn [] + (if (= 0 @prop) + [:div "Ok"] + (throw (js/Error. "foo"))))] + (wrap-capture-window-error + (wrap-capture-console-error + #(with-mounted-component [component [bad-component]] + (fn [c div] + (is (found-in #"Ok" div)) + (swap! prop inc) + (r/flush) + (is (found-in #"Error" div))))))))) + +(deftest get-snapshot-before-update-test + (when isClient + (let [ref (react/createRef) + prop (r/atom 0) + did-update (atom nil) + component (r/create-class + {:get-snapshot-before-update (fn [this [_ prev-props] prev-state] + {:height (.. ref -current -scrollHeight)}) + :component-did-update (fn [this [_ prev-props] prev-state snapshot] + (reset! did-update snapshot)) + :render (fn [this] + (r/as-element + [:div + {:ref ref + :style {:height "20px"}} + "foo"]))}) + component-2 (fn [] + [component {:value @prop}])] + (with-mounted-component [component-2] + (fn [c div] + ;; Attach to DOM to get real height value + (.appendChild js/document.body div) + (is (found-in #"foo" div)) + (swap! prop inc) + (r/flush) + (is (= {:height 20} @did-update)) + (.removeChild js/document.body div)))))) From 555ae05947079b33ac36ef42aea4a3ac59acda7b Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Wed, 14 Aug 2019 10:52:51 +0300 Subject: [PATCH 5/6] Update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db1e246..e480b00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,13 @@ **[compare](https://github.com/reagent-project/reagent/compare/v0.8.1...master)** +- Default to React 16.9 - Fix using `with-let` macro in namespaces with `*warn-on-infer*` enabled ([#420](https://github.com/reagent-project/reagent/issues/420)) - Fix using metadata to set React key with Fragment shortcut (`:<>`) ([#401](https://github.com/reagent-project/reagent/issues/401)) - Create React Component without `create-react-class` ([#416](https://github.com/reagent-project/reagent/issues/416)) + - `React.Component` doesn't have `getInitialState` method, but this is implemented by + Reagent for compatibility with old components. + - `constructor` can be used to initialize components (e.g. set the state) - Allow any number of arguments for `reagent.core/merge-props` and ensure `:class` is merged correctly when it is defined as collection. ([#412](https://github.com/reagent-project/reagent/issues/412)) - Add `reagent.core/class-names` utility functions which can be used @@ -17,6 +21,9 @@ uses correct Object interop forms, allowing use of ClojureScript `:checked-array - Deprecated `reagent.interop` namespace - It is better to use proper object interop forms or `goog.object` functions instead. - Drop `:export` metadata from `force-update-all` function +- `componentWillReceiveProps`, `componentWillUpdate` and `componentWillMount` lifecycle methods are deprecated + - Using these directly will show warning, using `UNSAFE_` prefixed version will silence the warning. + - These methods will continue to work with React 16.9 and 17. ## 0.8.1 (2018-05-15) From 094a29b9dfa67140bdc836fafa36078f25cbcb2a Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Wed, 14 Aug 2019 10:53:05 +0300 Subject: [PATCH 6/6] Fix accessing js state in optimized build --- test/reagenttest/testreagent.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/reagenttest/testreagent.cljs b/test/reagenttest/testreagent.cljs index eb9426a..904aaf1 100644 --- a/test/reagenttest/testreagent.cljs +++ b/test/reagenttest/testreagent.cljs @@ -1282,7 +1282,7 @@ ;; "Expensive" calculation based on the props #js {:v (string/join " " (repeat (inc (:value props)) "foo"))}) :render (fn [this] - (r/as-element [:p "Value " (.-v (.-state this))]))}) + (r/as-element [:p "Value " (gobj/get (.-state this) "v")]))}) component (fn [] [pure-component {:value @prop}])] (with-mounted-component [component]