如何为一个简单的Fulcro应用设置动态UI路由?

问题描述 投票:0回答:1

我已经爬过了一些......"。网络视频 路由的文档。但我无法让动态UI路由在一组简单的页面上工作。

root.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}))

client.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.

>> UPDATE <<

我能够得到一个有效的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 看起来像这样。

reactjs clojurescript fulcro
1个回答
0
投票

我想你首先要解决Index组件的Ident问题。

其他组件的路由是否有效?


0
投票

我认为你的Root初始状态应该是调用 (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. 这就是为什么你还需要更新初始状态来调用 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_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]}}))))}
© www.soinside.com 2019 - 2024. All rights reserved.