问题
I have a ClojureScript component:
(defn main-panel []
(def nodes (-> @(re-frame/subscribe [::subs/nodes])))
(defn list-nodes [node]
(prn (node :name)))
(reagent/create-class
{:component-did-mount
(fn []
(api-service/get-file-tree))
:reagent-render
(fn []
(doseq [node nodes]
(if (= (node :depth) 0)
(list-nodes node))))}))
which prints strings to the console.
But when I change the first function to:
(defn list-nodes [node]
[:<>
[:h1 (node :name)]])
I don't get any html that is rendered - no errors and the browser window stays blank.
How can I change this so it renders html? Thanks in advance.
Update
In response to the answer below I have changed doseq
for for
.
The issue is now that I am getting the error Uncaught Invariant Violation: Objects are not valid as a React child
which is fine if you're working with React because you can debug, but with reagent, not so much. consider the following. This function:
(defn node [nodes]
(prn (nodes :name)))
when called by this function:
:reagent-render
(fn []
(for [nodes all-nodes]
(if (= (nodes :depth) 0)
(do
(nodeComponent/node nodes)
))))
prints 5 strings. But changing the called function to this:
(defn node [nodes]
[:h1 (nodes :name)])
causes this error: Uncaught Invariant Violation: Objects are not valid as a React child
.
Is this problem somehow related to another problem I'm having? Thanks in advance.
回答1:
For one, def
and defn
create global bindings. In order to create local bindings, use let
or letfn
:
(defn main-panel []
(let [nodes (-> @(re-frame/subscribe [::subs/nodes]))
(letfn [(list-nodes [node]
(prn (node :name)))]
(reagent/create-class
{:component-did-mount
(fn []
(api-service/get-file-tree))
:reagent-render
(fn []
(doseq [node nodes]
(if (= (node :depth) 0)
(list-nodes node))))}))
Your problem is that the render function should return the hiccup forms, but doseq
returns nil
. The function inside gets run (that's why you see console output from prn
), but its return value is thrown away (that's why you see no HTML). An immediate fix might be to replace doseq
with for
, but
You could maybe do it like this (first reagent form):
(defn main-panel []
[:ul (for [node @(re-frame/subscribe [::subs/nodes])
:when (zero? (:depth node))]
^{:key (:id node)} ; whatever identifies nodes, for performance
[:li {:class "node"} (:name node)]])
I would trigger data fetching not here but wherever you startup your application (more or less parallel to the initial app render step).
来源:https://stackoverflow.com/questions/57903325/clojurescript-function-prints-strings-but-will-not-return-hiccup