在下面的代码中,我调度了两个单击事件:
;; 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]
,但是给出了同样的错误。一般来说,如何正确调度两个事件?
这是正确的:
(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对象。reg-event-fx
代替reg-event-db
。虽然稍微冗长一些,但它会使人眼更加清楚db
中的值。