ClojureScript function prints strings, but will not return hiccup

心不动则不痛 提交于 2019-12-25 01:44:07

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!