微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Reagent/Clojurescript 中向 UI 显示错误的模式

如何解决在 Reagent/Clojurescript 中向 UI 显示错误的模式

在使用 Reagent 应用程序时,我经常发现自己做这样的事情。

(defn create-account [user-details error-ref]
  (let [validation-errors (do-validations user-details)]
    (if validation-errors
      (reset! error-ref validation-errors)
      (finish-create))))


(defn component []
   (let [user-details (atom {:email "" :password ""})
          ui-errors (atom nil)]
        (fn []
          [:div.Page
            (if @ui-errors
              [:p @ui-errors])
            [:input {:type "text" :placeholder "EMAIL" :on-change #(swap! user-details conj {:email (-> % .-target .-value)})}]
            [:input {:type "password" :placeholder "PASSWORD" :on-change #(swap! user-details conj {:password (-> % .-target .-value)})}]
            [:button.bottomMargin {:on-click #(create-account @user-details ui-errors)} "Submit"]])))

我将设置一个原子来处理存储发生的任何错误并将其传递到我的注册流程中。这很简单,因为我可以用任何错误更新原子并将它们显示用户

我担心的是,这感觉不太实用。我知道我在我的块中更新了这个原子,这感觉就像是破坏了函数纯度的副作用。我也不喜欢将原子传递到我的函数中的唯一目的是在错误状态下进行更新。

我想如果我想向我的用户显示错误,我将不得不在我的代码中的某个点产生副作用,但我想看看是否有更好的或接受这样做的模式。我觉得我的植入工作正常,但功能并不像我喜欢的那么好,如果处理或验证数据的流程增加,可能很难维护。

解决方法

像这样将状态放在它自己的命名空间中的单个原子中。警告:我还没有真正测试过这段代码。

(ns my.app.db
  (:require [reagent.ratom :as r]))

(def default-db {})

(def my-db (r/atom default-db))

(defn init-db! []
  (reset! my-db default-db))


(defn new-account [user]
  (let [validation-errors (do-validation user)]
    (if validation-errors
      {:valid? false :errors validation-errors}
      {:valid? true :user user})))


(defn create-account! [user]
  (swap! my-db assoc :account (new-account user)))

然后在您的 UI 代码中:



(ns my.app.ui
  (:require [my.app.db :as db]))

(defn user-form [{:keys [valid? user errors]}]
  (fn []
    [:div.Page
      (if-not valid?
        [:p errors])
     [:input {:type "text" :placeholder "EMAIL"
              :on-change #(swap! db/my-db assoc-in [:account :user :email] (-> % .-target .-value))
              :default-value (:email user)}
      [:input {:type "password" :placeholder "PASSWORD"
               :on-change #(swap! db/my-db assoc-in [:account :user :password] (-> % .-target .-value))
               :default-value (:password user)}]
      [:button.bottomMargin {:on-click #(db/create-account! user)} "Submit"]]]))


(defn parent-component []
  (let [db @db/my-db]
    (fn []
      [user-form (:account db)])))

您可能还需要检查表单是否脏,向 :account 映射添加另一个属性,这样您就不会在用户为 nil 时尝试显示错误。但是这样的事情很快就会变得混乱,因此我建议您使用 fork 之类的东西进行表单管理,它与试剂配合得很好。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?