我喜欢 re-frame,但我意识到我在寻找处理 AJAX 响应的好模式时遇到了一些麻烦。
我的情况如下:
我有一个“全局”事件处理程序,它触发一些 AJAX 调用并调度到其他一些全局事件处理程序,具体取决于该调用是否成功,例如:
(reg-event-db :store-value
(fn [db [_ value]]
(do-ajax-store value
:on-success #(dispatch [:store-value-success %])
:on-error #(dispatch [:store-value-error %])
db))
(reg-event-db :store-value-success
(fn [db [_ result]]
(assoc db :foobar result)))
(reg-event-db :store-value-error
(fn [db [_ error]]
(assoc db :foobar nil
:last-error error)))
(我知道reg-event-fx
和东西,为了简洁起见,我只是在这里避免它,因为我认为它对我的问题没有任何影响)。
我还有(多个,不同的)可能触发:store-value
事件的 UI 组件,如下所示:
(defn button []
(let [processing? (reagent/atom false)]
(fn button-render []
[:button {:class (when @processing? "processing")
:on-click (fn []
(reset! processing? true)
(dispatch [:store-value 123]))}])))
因此,在这种情况下,组件具有本地状态 ( processing?
),它应该取决于 AJAX 调用是否仍在进行中。
现在,让button
组件对事件做出反应:store-value-success
并在AJAX 调用完成后将标志:store-value-error
重置processing?
回的正确模式是什么?false
目前,我正在通过传递回调来解决这个问题,但这看起来真的很难看,因为它使事件处理程序的代码与不属于那里的东西混杂在一起。
我想到的最好的解决方案是让button
组件能够挂钩:store-value-success
和:store-value-error
事件并为这些事件安装自己的处理程序,如下所示:
(defn button []
(let [processing? (reagent/atom false)]
(reg-event-db :store-value-success
(fn [db _]
(reset! processing? false)))
(reg-event-db :store-value-error
(fn [db _]
(reset! processing? false)))
(fn button-render []
[:button {:class (when @processing? "processing")
:on-click (fn []
(reset! processing? true)
(dispatch [:store-value 123]))}])))
但是,这是行不通的。看起来,重新框架不允许每个事件有多个事件处理程序。相反,reg-event-db
对单个事件 id 的后续调用将替换先前的事件处理程序。
那么你们是如何处理这种情况的呢?