ratom update within render function does not cause a re-render
john-shaffer opened this issue · 2 comments
Reagent version: 1.1.0
Repro:
(defn DocsBad []
(let [state (r/atom {:versions nil})]
(fn []
(let [state* @state
{:keys [versions]} @state
version-entity-ids [1]]
(when (not= versions version-entity-ids)
(swap! state assoc :versions (vec version-entity-ids)))
[:div (pr-str state* @state)]))))
Expected: Component renders at least twice and results in [:div "{:versions 1} {:versions: 1}"]
.
Actual: Component renders once and results in in [:div "nil {:versions 1}"]
(unless something else causes a render).
I tried using this component in a project, and I'm seeing {:versions [1]} {:versions [1]}
rendered. I also tried adding some console.logs on the fn body and inside when
form, and I can see the update is called once and render is first called with {:versions nil}
and then with the updated value.
If I run the code which @john-shaffer provided as is (reproduced here for clarity)...
(defn DocsBad []
(let [state (r/atom {:versions nil})]
(fn []
(let [state* @state
{:keys [versions]} @state
version-entity-ids [1]]
(when (not= versions version-entity-ids)
(swap! state assoc :versions (vec version-entity-ids)))
[:div (pr-str state* @state)]))))
...I get {:versions nil} {:versions [1]}
. The view component is being rendered once.
It may help to share that if I run the following modified code...
(defn DocsBad []
(let [state (r/atom {:versions nil})]
(fn []
(let [state* @state
{:keys [versions]} @state
version-entity-ids [1]]
(when (not= versions version-entity-ids)
(r/next-tick (partial swap! state assoc :versions (vec version-entity-ids))))
[:div (pr-str state* @state)]))))
...I get {:versions [1]} {:versions [1]}
. The view component is being rendered twice.
Note that the difference merely involves using the next-tick
Reagent function, so that the swap!
is the tiniest bit deferred.