使用Reagent进行Ajax GET请求

10
我正在从我的Reagent应用程序进行Ajax GET,以从数据库中加载一些内容。
我不确定获取此类ajax调用的结果并将其放入原子中是最佳方法,考虑到如果我将其放在原子中,则当取消引用原子时,Reagent会自动重新呈现组件,这意味着我会得到一个无限序列的ajax调用。
以下是一些代码:
(def matches (atom nil))

(defn render-matches [ms]
  (reset! matches (into [:ul] (map (fn [m] ^{:key m}[:li m])
                                   (walk/keywordize-keys (t/read (t/reader :json) ms)))))

这个函数基本上创建了一个[:ul [:li "这里的东西"] [:li "还有这里"]]

我想在我的页面上显示它,现在代码如下。

(defn standings-page []
  (GET "/list-matches"
       {:handler render-matches})
  @matches)

GET请求是如何触发的?在页面加载时?还是只有在需要那个试剂组分时才触发?或者是用户操作?你在这里混杂了很多东西。我只会把数据(而不是hiccups)放入原子中,并在standings-page中呈现列表。如果您只需要请求一次,可以尝试使用delay并引用standings-page中的延迟。但是,这取决于您的用例(因此是前几个问题)。 - ClojureMostly
不要直接从渲染函数中调用具有副作用的代码。可以在生命周期函数(如will-mount或did-mount)中执行,或者在reagent组件初始化中执行(如Michiel Borkent的答案所示)。 - user21037
1个回答

12

我认为最好只在一个原子中保存数据并将HTML作为组件逻辑的一部分生成。

此外,最好在渲染阶段之外触发AJAX调用,例如在组件挂载之前或作为事件(例如按钮点击)的结果。

像这样:

(def matches (atom nil))
(defn component []
  (let [get-stuff (fn [] (GET "/..." :handler (fn [response] 
                           (reset! matches (:body response))))]
    (get-stuff) <-- called before component mount
    (fn []
      [:ul
        (for [m match]
          ^{:key ...} 
          [:li ...])])))

这在这篇文章中被称为表单2。


1
谢谢Michiel。你的评论非常有帮助,我对逻辑有了更好的理解 :) 在Meetup上见! - Helios
1
难道 form-2 的关键不是你返回一个函数吗?如果是这样,为什么需要使用 let?你不能这样做吗:(def matches (atom nil) (defn component [] (GET "/..." :handler (fn [response] (reset! matches (:body response)))) (fn [] [:ul (for [m match] ^{:key ...} [:li ...])])) - DandyDev
@DandyDev,你可以这样做。我只是创建了这个名称来表达意图,但你可以不使用这个函数。 - Michiel Borkent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接