-
Notifications
You must be signed in to change notification settings - Fork 10
component states
Crossing components states updating is a little confusing in Respo. But I tried to make inner-component states updating to be easier:
(defn on-click [state]
(fn [e dispatch! mutate!]
(mutate! (update state :count inc))))
The mutate!
function above just updates component state.
states
is stored globally in store
:
(defonce store (atom {:states {}}))
It's represented in tree, I call the paths to each node "cursors". And by getting a cursor, you may know where to update the states. A simple way to specify a sub-cursor is like this:
(cursor-> :sub-cursor comp-demo states p1 p2)
which expands to:
(assoc (comp-demo (:sub-cursor states) p1 p2) :cursor (conj *cursor* :sub-cursor))
where *cursor*
was passed in from the macro defcomp
.
Currently when you write:
(def initial-state {:count 1})
(defn on-click [state]
(fn [e dispatch! mutate!]
(mutate! (update state :count inc))))
(defcomp comp-demo [states]
(let [state (or (:data states) initial-state)])
(div {}
(<> div (str (:count 1)) nil)
(=< 8 0)
(button {:inner-text "inc"
:on {:click (on-click state)}})))
after macros expanded it becomes:
(def initial-state {:count 1})
(defn on-click [state]
(fn [e dispatch! mutate!]
(mutate! (update state :count inc))))
(def comp-demo
(create-comp
(fn [states]
(fn [*cursor*]
(let [state (or (:data states) initial-state)])
(create-element :div {}
(div {:inner-text (str (:count 1)), :style nil})
(comp-space 8 0)
(button {:inner-text "inc"
:on {:click (on-click state)}}))))))
It looks tedious but you can see *cursor*
in the code.
And we can pass *cursor*
explicitly to show how it works:
(def initial-state {:count 1})
(defn on-click [*cursor* state]
(fn [e dispatch! mutate!]
; (mutate! (update state :count inc))
(dispatch! :states [*cursor* (update state :count inc)])))
(def comp-demo
(create-comp
(fn [states]
(fn [*cursor*]
(let [state (or (:data states) initial-state)])
(create-element :div {}
(div {:inner-text (str (:count 1)), :style nil})
(comp-space 8 0)
(button {:inner-text "inc"
:on {:click (on-click *cursor* state)}}))))))
So mutate!
is only a small wrapper based on #(dispatch! :states [*cursor* %])
.
And you can even call (mutate! *cursor* s)
to pass a specific cursor.
(fn
([next-state] (dispatch! :states [this-cursor next-state]))
([*cursor* next-state] (dispatch! :states [*cursor* next-state])))
So if the cursor is passed down from a parent component, then you can update parent states.