Can't update state with transact! in Om

388 views Asked by At

In the local-state example in the om-cookbook, I'm able to update the counter using update-state! and set-state!, but not with transact!

I initialized project using chestnut template.

(def app-state (atom {:button-presses 0}))

These work

(defn clicks [data owner]
  (om/update-state! owner [:button-presses] inc))

(defn clicks [data owner]
  (let [value (om/get-state owner :button-presses)]
    (om/set-state! owner :button-presses (inc value))))

This doesn't work

(defn clicks [data owner]
  (om/transact! data :button-presses inc))

Call from IRenderState

om/IRenderState
    (render-state [_ state]
              (dom/div nil
                       (dom/button #js
                                   {:onClick #(clicks data owner)}
                                   "Click Moi")
                       (dom/br nil)
                       (dom/p nil
                              (str "Button Presses: " (:button-presses state)))))))
2

There are 2 answers

0
Dominykas Mostauskis On

You are confusing application state and a component's state. Notice how update-state! and set-state! take owner (the component) as argument, while transact! and update! take a cursor.

(defn clicks [data owner]
  (om/transact! data :button-presses inc))

Your above example actually acts on the cursor (data), not the state, but your IRenderState implementation is looking up :button-presses on component's state. If you changed (:button-presses state) to (:button-presses data) everything should be fine.

0
Vlad A. On

As per Om Dcumentation, you are using transact! and passing it a function but not a function applied to the old state. You can either do a

(defn clicks [data owner] (om/transact! data :button-presses #(apply inc %))

or simply (partial inc) which will expect the value to be passed in.

Also as a side note, the only difference between transact! and update! is that update! disregards the arguments (the old value of the cursor)