0

我已经浏览了一些用于路由的网络视频文档。但我无法让动态 UI 路由为一组简单的页面工作。

根.cljs

(ns ui.root)
;; ...

(defsc Index [this props]
  {:query [:index]
   :ident (fn [] [:id :index])
   :route-segment ["index"]
   :initial-state {}}

  (h3 "Index"))

(defsc Landing [this props]
  {:query [:landing]
   :ident (fn [] [:id :landing])
   :route-segment ["landing"]
   :initial-state {}}

  (h3 "Landing"))

(defsc Settings [this props]
  {:query [:settings]
   :ident (fn [] [:id :settings])
   :route-segment ["settings"]
   :initial-state {}}

  (h3 "Setting"))


(dr/defrouter TopRouter [this {:keys [current-state] :as props}]
  {:router-targets [Game Settings Landing Index]
   :initial-state (fn [{:keys [current-state]}]
                    {:current-state current-state})}

  (case current-state
    :pending (dom/div "Loading...")
    :failed (dom/div "Failed!")
    (dom/div "No route selected.")))

(def ui-top-router (comp/factory TopRouter))


(defsc Root [this {:keys [router] :as props}]
  {:query [{:router (comp/get-query TopRouter)}]
   :ident (fn [] [:id :root])

   :initial-state (fn [_]
                    {:top-router (comp/get-initial-state TopRouter {:current-state :pending})
                     :index {:id 1}
                     :landing {:id 1}
                     :settings {:id 1}})

   :componentDidMount (fn [_] (log/info "Root Initial State /" (prim/get-initial-state Root {})))}

  (log/info "Root Props /" this props)
  (ui-top-router router {:current-state :pending}))

客户端.cljs

(ns client)
...

(app/mount! @app root/Root "app" {:initialize-state? true
                                  :foo :bar})

问:初始负载给出了这个输出。我们如何将 props 传递给 Root 组件?我希望至少能看到{:foo :bar}

INFO [ui.root:81] - Root Props / [object Object] {}
INFO [ui.root:53] - TopRouter Props / {:current-state nil, :route-factory #object[cljs.core.MetaFn], :pending-path-segment nil, :route-props nil}
INFO [ui.root:77] - Root Initial State / nil

问:如果这是我的初始状态,:query:ident吗?它们 (:query + :ident) 是否对应于:route-segment?他们需要吗?

{:index {:id 1}
 :landing {:id 1}
 :settings {:id 1}}

问:我们如何开始初始路线?调用它失败并显示以下消息。

(dr/change-route app ["index"])

INFO [com.fulcrologic.fulcro.rendering.ident-optimized-render:146] - Optimized render failed. Falling back to root render.

>> 更新 <<

我能够获得一个有效的 Fulcro Root:initial-state:query:ident组件。

在初始加载时,路由器会因此而失败。

INFO [beatthemarket.ui.root:61] - TopRouter Props / {:current-state nil, :route-factory #object[cljs.core.MetaFn], :pending-path-segment nil, :route-props {:index/id 1, :index/text "Index Text"}}

core.cljs:159 ERROR [com.fulcrologic.fulcro.routing.dynamic-routing:410] - will-enter for router target beatthemarket.ui.root/Index did not return a valid ident. Instead it returned:  [:index/id nil]
core.cljs:159 ERROR [com.fulcrologic.fulcro.routing.dynamic-routing:410] - will-enter for router target beatthemarket.ui.root/Index did not return a valid ident. Instead it returned:  [:index/id nil]

browser.cljs:25 shadow-cljs: WebSocket connected!
browser.cljs:25 shadow-cljs: REPL session start successful

core.cljs:159 INFO [com.fulcrologic.fulcro.algorithms.indexing:104] - component beatthemarket.ui.root/Index's ident ([:index/id nil]) has a `nil` second element. This warning can be safely ignored if that is intended.

所以像这样的命令(dr/change-route app (dr/path-to root/Index))失败了。

react_devtools_backend.js:6 ERROR [com.fulcrologic.fulcro.routing.dynamic-routing:410] - will-enter for router target beatthemarket.ui.root/Index did not return a valid ident. Instead it returned:  [:index/id nil]

这些是我的client.cljsroot.cljs看起来像这样。

4

2 回答 2

0

我想您首先必须解决 Index 组件的 Ident 问题。

路由是否适用于其他组件?

于 2020-04-27T14:22:44.150 回答
0

我认为您的 Root 初始状态应该是 call (comp/get-initial-state Index)。您在 Index 上设置了初始状态,但它与 Root 给出的初始状态不同。

此外,Fulcro(和 React)的很大一部分是您构建组件树和数据树,它们需要匹配。

你在这里的方式,“Root”和“Index”之间没有联系,因为 Root 只渲染(ui-top-router router). 您通过查询获取 Index 的数据,{:root/index (comp/get-query Index)}但您没有通过让 Root 调用 Index 并传入该数据来创建 Root 和 Index 之间的连接。你需要一个(ui-index index)内部根。

如果您这样做,那么在该(ui-index index)调用中,index将采用您设置的值:initial-state。这就是为什么您还需要更新 initial-state 以调用comp/get-initial-state,以便您可以获取:index/id 1您在 Index 组件的初始状态中设置的值。

(defsc Index [this {:index/keys [id text]}]
  {:query [:index/id :index/text]
   :ident [:index/id :index/id]
   :route-segment ["index"]
   :initial-state {:index/id 1
                   :index/text :param/text}}

  (h3 text))

(defsc Root [this {:root/keys [router index landing game settings]}]
  {:query [{:root/router (comp/get-query TopRouter)}
           {:root/index (comp/get-query Index)}
           {:root/landing (comp/get-query Landing)}
           {:root/game (comp/get-query Game)}
           {:root/settings (comp/get-query Settings)}]

   :initial-state {:root/router {}
                   :root/index {:text "Index Text"}
                   :root/landing {:text "Landing Text"}
                   :root/game {:text "Game Text"}
                   :root/settings {:text "Settings Text"}}}
  (when router
   (dom/div (ui-top-router router))))

在所有这些都解决之后,这是您可能感兴趣的下一件事。

您可能不会总是想要硬编码index/id 1. 您可能需要从服务器获取数据才能渲染任何内容。

这就是:will-enter“延迟路由”发挥作用的地方。请参阅下面的示例和http://book.fulcrologic.com/#_router_rendering_of_a_deferred_ui上的文档。

(defsc Person [this {:ui/keys      [modified?]
                     :person/keys  [id name]
                     :address/keys [city state]
                     :as           props}]
  {:query               [:ui/modified? :person/id :person/name :address/city :address/state]
   :ident               :person/id
   :route-segment       ["person" :person/id]
   :route-cancelled     (fn [{:person/keys [id]}]
                          (log/info "Routing cancelled to user " id))
   :allow-route-change? (fn [this {:ui/keys [modified?]}]
                          (when modified?
                            #?(:cljs (js/alert "You cannot navigate until the user is not modified!")))
                          (not modified?))
   :will-enter          (fn [app {:person/keys [id] :as route-params}]
                          (log/info "Will enter user with route params " route-params)
                          ;; be sure to convert strings to int for this case
                          (let [id (if (string? id) (edn/read-string id) id)]
                            (dr/route-deferred [:person/id id]
                                               #(df/load app [:person/id id] Person
                                                         {:post-mutation        `dr/target-ready
                                                          :post-mutation-params {:target [:person/id id]}}))))}
于 2020-07-07T13:23:01.460 回答