Skip to content

Commit

Permalink
Fix #548: Support function-component version of reactify-component
Browse files Browse the repository at this point in the history
  • Loading branch information
Deraen committed Dec 19, 2021
1 parent 8b3883e commit b741fdf
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 20 deletions.
58 changes: 39 additions & 19 deletions src/reagent/impl/component.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -346,31 +346,51 @@
(gobj/set c (p/get-id compiler) constructor)
constructor)

(defn fn-to-class [compiler f]
(assert-callable f)
(warn-unless (not (and (react-class? f)
(not (reagent-class? f))))
"Using native React classes directly in Hiccup forms "
"is not supported. Use create-element or "
"adapt-react-class instead: " (or (util/fun-name f)
f)
(comp-name))
(if (reagent-class? f)
(cache-react-class compiler f f)
(let [spec (meta f)
withrender (assoc spec :reagent-render f)
res (create-class withrender compiler)]
(cache-react-class compiler f res))))

(defn as-class [tag compiler]
(defn as-component [compiler tag]
(if-some [cached-class (cached-react-class compiler tag)]
cached-class
(fn-to-class compiler tag)))
(do
(assert-callable tag)
(warn-unless (not (and (react-class? tag)
(not (reagent-class? tag))))
"Using native React classes directly in Hiccup forms "
"is not supported. Use create-element or "
"adapt-react-class instead: " (or (util/fun-name tag)
tag)
(comp-name))
(if (reagent-class? tag)
(cache-react-class compiler tag tag)
(let [spec (meta tag)
withrender (assoc spec :reagent-render tag)
res (create-class withrender compiler)]
(cache-react-class compiler tag res))))))

(declare functional-render-fn)

(defn as-component-functional [compiler tag]
(if-some [cached-class (cached-react-class compiler tag)]
cached-class
(do
(js/console.log "as-component-functional")
(assert-callable tag)
(warn-unless (not (and (react-class? tag)
(not (reagent-class? tag))))
"Using native React classes directly in Hiccup forms "
"is not supported. Use create-element or "
"adapt-react-class instead: " (or (util/fun-name tag)
tag)
(comp-name))
(if (reagent-class? tag)
(cache-react-class compiler tag tag)
(let [res (fn [js-props]
(p/as-element compiler [tag js-props]))]
(js/console.log "foo" tag)
(cache-react-class compiler tag res))))))

(defn reactify-component [comp compiler]
(if (react-class? comp)
comp
(as-class comp compiler)))
(p/as-component compiler comp)))

(defn functional-wrap-render
[compiler ^clj c]
Expand Down
1 change: 1 addition & 0 deletions src/reagent/impl/protocols.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
(get-id [this])
(parse-tag [this tag-name tag-value])
(as-element [this x])
(as-component [this tag])
(make-element [this argv component jsprops first-child]))

7 changes: 6 additions & 1 deletion src/reagent/impl/template.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@
fn-to-element (if (:function-components opts)
maybe-function-element
reag-element)
fn-to-component (if (:function-components opts)
comp/as-component-functional
comp/as-component)
parse-fn (get opts :parse-tag cached-parse)]

(reify p/Compiler
Expand All @@ -314,7 +317,9 @@
(as-element [this x]
(as-element this x fn-to-element))
(make-element [this argv component jsprops first-child]
(make-element this argv component jsprops first-child)))))
(make-element this argv component jsprops first-child))
(as-component [this tag]
(fn-to-component this tag fn-to-element)))))

(def default-compiler* (create-compiler {}))
(def ^:dynamic default-compiler default-compiler*)
Expand Down
16 changes: 16 additions & 0 deletions test/reagenttest/testreagent.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -1750,3 +1750,19 @@
(gobj/clear tag-name-cache)
(is (= "<div class=\"foo_asd foo_xyz bar\"></div>"
(as-string [:div.asd.xyz {:class "bar"}] compiler)))))

(deftest functional-component-reactify-component
(when r/is-client
(let [set-count! (atom nil)
c (fn [{:keys [x]}]
(let [[c set-count] (react/useState x)]
(reset! set-count! set-count)
[:span "Count " c]))
react-cmp (r/reactify-component c functional-compiler)]
(with-mounted-component [:r> react-cmp #js {:x 1}]
functional-compiler
(fn [c div]
(is (nil? c) "Render returns nil for stateless components")
(is (= "Count 5" (.-innerText div)))
(@set-count! 6)
(is (= "Count 6" (.-innerText div))))))))

0 comments on commit b741fdf

Please sign in to comment.