diff --git a/src/reagent/impl/component.cljs b/src/reagent/impl/component.cljs index 6fe4ea16..9320a597 100644 --- a/src/reagent/impl/component.cljs +++ b/src/reagent/impl/component.cljs @@ -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] diff --git a/src/reagent/impl/protocols.cljs b/src/reagent/impl/protocols.cljs index f97e0132..1b96c7db 100644 --- a/src/reagent/impl/protocols.cljs +++ b/src/reagent/impl/protocols.cljs @@ -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])) diff --git a/src/reagent/impl/template.cljs b/src/reagent/impl/template.cljs index 959f67e8..263f372c 100644 --- a/src/reagent/impl/template.cljs +++ b/src/reagent/impl/template.cljs @@ -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 @@ -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*) diff --git a/test/reagenttest/testreagent.cljs b/test/reagenttest/testreagent.cljs index 26cd3bcb..a7e9b5b6 100644 --- a/test/reagenttest/testreagent.cljs +++ b/test/reagenttest/testreagent.cljs @@ -1750,3 +1750,19 @@ (gobj/clear tag-name-cache) (is (= "
" (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))))))))