From 87b61475e20fb31735ffc03e77eaf78f692879d9 Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Mon, 12 Mar 2018 13:53:48 +0200 Subject: [PATCH] Implement :<> hiccup tag for fragments Fixes #319 --- src/reagent/impl/template.cljs | 16 ++++++++++++-- test/reagenttest/testreagent.cljs | 36 ++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/reagent/impl/template.cljs b/src/reagent/impl/template.cljs index 7aabd4d..70d65b2 100644 --- a/src/reagent/impl/template.cljs +++ b/src/reagent/impl/template.cljs @@ -10,6 +10,8 @@ [reagent.debug :refer-macros [dbg prn println log dev? warn warn-unless]])) +(declare as-element) + ;; From Weavejester's Hiccup, via pump: (def ^{:doc "Regular expression that parses a CSS-style id and class from a tag name."} @@ -342,6 +344,15 @@ ($! jsprops :key key)) (react/createElement c jsprops))) +(defn fragment-element [argv] + (let [props (nth argv 1 nil) + hasprops (or (nil? props) (map? props)) + jsprops (convert-prop-value (if hasprops props)) + first-child (+ 1 (if hasprops 1 0))] + (when-some [key (key-from-vec argv)] + (oset jsprops "key" key)) + (make-element argv react/Fragment jsprops first-child))) + (defn adapt-react-class ([c {:keys [synthetic-input]}] (let [on-update (:on-update synthetic-input) @@ -383,8 +394,6 @@ s (aset tag-name-cache x (parse-tag x)))) -(declare as-element) - (defn native-element [parsed argv first] (let [comp ($ parsed :name) synthetic-input ($ parsed :syntheticInput)] @@ -429,6 +438,9 @@ (let [tag (nth v 0 nil)] (assert (valid-tag? tag) (hiccup-err v "Invalid Hiccup form")) (cond + (keyword-identical? :<> tag) + (fragment-element v) + (hiccup-tag? tag) (let [n (name tag) pos (.indexOf n ">")] diff --git a/test/reagenttest/testreagent.cljs b/test/reagenttest/testreagent.cljs index 9968f8f..ce95151 100644 --- a/test/reagenttest/testreagent.cljs +++ b/test/reagenttest/testreagent.cljs @@ -252,7 +252,7 @@ (is (= 2 @ran))))) (defn as-string [comp] - (server/render-to-string comp)) + (server/render-to-static-markup comp)) (deftest to-string-test [] (let [comp (fn [props] @@ -1125,3 +1125,37 @@ (fn [c div] (is (= "parent,child,bar" (.-innerText div)))))) + + +(deftest test-fragments + (when (>= (js/parseInt react/version) 16) + (testing "Fragment as array" + (let [comp (fn [] + #js [(r/as-element [:div "hello"]) + (r/as-element [:div "world"])])] + (is (= "
hello
world
" + (as-string [comp]))))) + + (testing "Fragment element, :<>" + (let [comp (fn [] + [:<> + [:div "hello"] + [:div "world"] + [:div "foo"] ])] + (is (= "
hello
world
foo
" + (as-string [comp]))))) + + (testing "Fragment key" + ;; This would cause React warning if both fragements didn't have key set + (let [comp (fn [] + [:div + (list + [:<> + {:key 1} + [:div "hello"] + [:div "world"]] + ^{:key 2} + [:<> + [:div "foo"]])])] + (is (= "
hello
world
foo
" + (as-string [comp])))))))