我目前正在尝试使用om并尝试加载外部数据以在组件中显示它。
我的详细信息组件:
(defn detail-component [app owner opts]
(reify
om/IInitState
(init-state [_]
(om/transact! app [:data] (fn [] "Test")))
om/IWillMount
(will-mount [_]
(go (let [foo (<! (fetch-something 1))]
(om/update! app #(assoc % :data foo))
)))
om/IRender
(render [_]
(dom/div nil
(dom/h1 nil "Foo")
(om/build another-component app)
)
))
)
(fetch-something
正在从API检索数据)。
(defn another-component [{:keys [data]}]
(om/component
(.log js/console data)
(dom/h2 nil "Another component goes here")
(dom/h2 nil (data :description))
)
)
总而言之,detail-component在挂载之前获取数据,将其附加到app
并构建another-component
。 another-component
然后从该数据中获取描述并显示它。
然而,在执行时,我正在尝试访问描述时获得Uncaught TypeError: Cannot read property 'call' of null
。这向我表明,在构建another-component
时,数据尚未存在且失败。
如何在数据可用时告诉om构建应用程序?或者我是否必须构建一些nil?
支票?
答案 0 :(得分:3)
使用状态的工作示例:
project.clj
(defproject asajax "0.0.1-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License - v 1.0"
:url "http://www.eclipse.org/legal/epl-v10.html"
:distribution :repo}
:min-lein-version "2.3.4"
:source-paths ["src/clj" "src/cljs"]
:dependencies [[org.clojure/clojure "1.6.0"]
[org.clojure/clojurescript "0.0-2371"]
[org.clojure/core.async "0.1.267.0-0d7780-alpha"]
[om "0.7.3"]
[com.facebook/react "0.11.2"]]
:plugins [[lein-cljsbuild "1.0.4-SNAPSHOT"]]
:hooks [leiningen.cljsbuild]
:cljsbuild
{:builds {:asajax
{:source-paths ["src/cljs"]
:compiler
{:output-to "dev-resources/public/js/asajax.js"
:optimizations :whitespace
:pretty-print true}}}})
core.cljs
(ns asajax.core
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[cljs.core.async :as async])
(:require-macros [cljs.core.async.macros :refer (go)]))
(enable-console-print!)
(def app-state (atom {}))
(defn another-component [{:keys [data]}]
(reify
om/IRenderState
(render-state [_ state]
(dom/div nil
;; (.log js/console data)
(dom/h2 nil "Another component goes here")
(dom/h2 nil (:description state))))))
(defn fetch-something [x]
(let [c (async/chan)]
(go
;; pretend a blocking call
;; wait for 2 sec
(<! (async/timeout 2000))
(>! c {:data "Roast peach & Parma ham salad"
:description "This is a lovely light starter with fantastic sweet, salty and creamy flavours"}))
c))
(defn detail-component [app owner opts]
(reify
om/IInitState
(init-state [_]
{:data "Test"})
om/IWillMount
(will-mount [_]
(go (let [foo (<! (fetch-something 1))]
;; (prn "GOT" foo)
(om/set-state! owner foo))))
om/IRenderState
(render-state [_ state]
(dom/div nil
(dom/h1 nil (:data state))
(om/build another-component app
{:state (om/get-state owner)})))))
(om/root
detail-component
app-state
{:target (. js/document (getElementById "app"))})
<强> UPDATE2 强>
这是一个使用sablono而不使用set-state!
添加到project.clj
[sablono "0.2.22"]
完整的core.cljs
(ns asajax.core
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[cljs.core.async :as async]
[sablono.core :as html :refer-macros [html]])
(:require-macros [cljs.core.async.macros :refer (go)]))
(enable-console-print!)
(def app-state (atom {:data "Initial"
:description "Loading..."}))
(defn another-component [{:keys [description]}]
(om/component
(html
[:.description
[:h2 "Another component"]
[:h2 description]])))
(defn fetch-something [x]
(let [c (async/chan)]
(go
;; pretend a blocking call
;; wait for 2 sec
(<! (async/timeout 2000))
(>! c {:data "Roast peach & Parma ham salad"
:description "This is a lovely light starter with fantastic sweet, salty and creamy flavours"}))
c))
(defn detail-component [app owner opts]
(reify
om/IWillMount
(will-mount [_]
(go (let [foo (<! (fetch-something 1))]
;; (prn "GOT" foo)
(om/update! app foo))))
om/IRender
(render [_]
(html [:div
[:h1 (:data app)]
(om/build another-component app)
]))))
(om/root
detail-component
app-state
{:target (. js/document (getElementById "app"))})