我试图创建一个重新订阅框架订阅,它从REST API而不是本地数据库读取数据,并将这些数据保存到数据库中。 REST调用依赖于重新框架数据库中的其他值(想想API-Key),虽然这些数据在通过应用程序导航时可用,但重新加载时却没有。我遵循本教程:https://github.com/Day8/re-frame/blob/master/docs/Subscribing-To-External-Data.md#some-code
我的订阅看起来像这样(为了便于阅读而被删除):
(rf/reg-sub-raw
:organisation-users
(fn [db [_ api-token organisation]]
(when (not (nil? api-token))]
(ajax/GET
(str "/some-url/to/get/users/for/organisation")
{:params {:api-token api-token}
:handler #(rf/dispatch [:organisation-users-change %])
:format (ajax/json-request-format)
:response-format (ajax/json-response-format {:keywords? true})}))
(ratom/make-reaction
(fn [] (:organisation-users @db)))))
订阅传递API-Key并从服务器请求组织用户。如果数据库中发生organisation-users
更改,则会返回更新订阅者的响应,该更改会在其余调用成功后立即发生。
在我的组件中,我订阅了订阅:
(defn organisation-page
[]
(let [api-token (rf/subscribe [:api-token])
organisation-users (rf/subscribe [:organisation-users @api-token])]
(fn []
[:div {:class "columns"}
))); stripped
如果我重新加载页面,并且在初始化(初始化api-token)之后让organisation-page
呈现,则此代码有效。在加载后立即呈现organisation-page
组件时,它不起作用,因为api-token尚未可用,并且它不会再次执行其余的调用。
我也尝试将整个订阅包装到反应中,但这会导致无限循环,因为每次数据库organisation-users
更改时都会执行整个反应,这会再次执行其余调用,从而触发反应等等。
我如何解决这个问题"重新框架方式"?我的一个想法是,如果organisation-users
尚未在数据库中填充,则仅执行其余调用。这可能会有效但我担心如果用户稍后导航到该页面并查看旧数据或者如果呼叫未成功并且用户无法通过再次导航到该页面来启动新尝试,则会遇到问题。
答案 0 :(得分:2)
我将用户的提取移动到了一个事件中。
为了测试它,我伪造了响应,但请注意,您可以使用http-fx非常好地嵌入ajax调用(请参阅注释掉的事件)。
请注意,由于subscription caching/deduplication,您可以立即取消订阅。
(ns simple.core
(:require [reagent.core :as r]
[re-frame.core :refer [reg-sub
reg-event-fx
reg-sub-raw
dispatch
subscribe
dispatch-sync]]))
(reg-sub
:api-token
(fn [db _]
(get db :api-token)))
(reg-event-fx
:api-token
(fn [{:keys [:db]} [_ api-token]]
{:db (assoc db :api-token api-token)}))
(reg-event-fx
:good-organisation-users
(fn [{:keys [:db]} [_ response]]
{:db (assoc db :organisation-users response)}))
(def responses {"123" [{:name "Foo"}]
"456" [{:name "Foo"} {:name "Bar"}]})
(reg-event-fx
:fetch-organisation-users
(fn [{:keys [:db]} [_ api-token]]
(.log js/console "fetching users with api-token" api-token)
{:dispatch [:good-organisation-users (get responses api-token)]}))
(defn fetch-users! []
(let [api-token @(subscribe [:api-token])]
(when api-token
(dispatch [:fetch-organisation-users api-token]))))
(reg-sub-raw
:organisation-users
(fn [app-db [_]]
(let [fetcher (r/track! fetch-users!)]
(reagent.ratom/make-reaction
(fn []
(get @app-db :organisation-users))
:on-dispose #(r/dispose! fetcher)))))
(defn organisation-page
[]
(let [organisation-users @(subscribe [:organisation-users])]
[:div
(when organisation-users
[:ul
(for [user organisation-users]
^{:key (:name user)}
[:li (:name user)])])]))
(defn ^:export run
[]
(dispatch [:api-token "123"])
(js/setTimeout #(dispatch [:api-token "456"]) 3000)
(r/render [organisation-page]
js/klipse-container))
(run)
要表明它有效,您可以在http://app.klipse.tech/?container&cljs_in.gist=borkdude/f228103b2eaa04b92c5b532485fbd2ef
实时查看