为什么数据库在重组中打印#object [Object [object Object]]?

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

在下面的代码中,我调度了两个单击事件:

;; event
(reg-event-db
 :some
 (fn [db [_ some-val]]
   (prn "The db is" db)
   (assoc db :some some-val)
   ))

;; another event
(reg-event-db
 :another
 (fn [db [_ another-val]]
   (prn "The db is" db)
   (assoc db :another another-val)
   ))

;; button
[:input {:type "button" :value "Button"
         :on-click #(do
                       (dispatch [:some :some-val])
                       (dispatch [:another :another-val]))}]

但不是打印数据库映射,而是打印"The db is" #object[Object [object Object]],然后

Error: No protocol method IAssociative.-assoc defined for type object: [object Object]

我做错了什么?我也尝试做#(dispatch [:some :some-val :another another-val],但是给出了同样的错误。一般来说,如何正确调度两个事件?

clojurescript re-frame
1个回答
0
投票

这是正确的:

(do
  (dispatch [:first-event :some-value])
  (dispatch [:second-event :other-value]))

这是不是正确:

(dispatch [:some :some-val :another another-val])

在此示例中,您要调度一个带有3个参数的事件:

  • :some是事件名称,
  • :some-val是第一个参数,
  • :another是第二个参数,
  • another-val是第三个参数。

您遇到的错误不是来自dispatch事件的方式,而是来自db状态。让我们逐步剖析它:

如果(prn db)输出#object[Object [object Object]],则表示db是JavaScript对象。

如果(assoc db …)失败并显示No protocol method IAssociative.-assoc defined for type object: [object Object],则表示db值不支持assoc功能。 assoc函数由协议(思考接口)定义,并且此协议在地图上实现。因此,这里db不是地图。

为什么db将成为JavaScript对象而不是Clojure映射?

当使用(reg-event-db :event-name handler-function)时,handler-function返回的值将替换db状态。如果错误地返回了JS对象,它将成为新的db值,并且此新的不正确的db值将传递给后续事件处理程序。因此,您的事件处理程序之一正在返回JavaScript对象。

我将如何解决这种情况:

  • 使用(js/console.log db)代替(prn db)。您将能够看到此js对象中的内容。 prn不知道如何正确打印js对象。
  • 确保cljs-devtools已安装并正在运行。它使您可以在控制台中浏览复杂的对象。下次出现此问题时,您将立即看到有问题的值而不是不透明的字符串表示形式。
  • 使用reg-event-fx代替reg-event-db。虽然稍微冗长一些,但它会使人眼更加清楚db中的值。
  • 如果您想进一步确保不再发生这种情况,请查看Re-Frame Middlewares。在您的情况下,中间件将允许您对返回值的处理程序进行操作,如果它不符合您的期望,则有可能拒绝它。
© www.soinside.com 2019 - 2024. All rights reserved.