Let's take a look at a canonical example of a Form 2 component.
(defn app-view []
(let [counter (r/atom 0)] ;; setup
(fn [] ;; render fn
[:div
[:p @counter]
[:button
{:on-click
(fn [e]
(swap! counter inc))}
"Increment!"]])))
We initialize some local state and return a function that returns some Hiccup. On click, we would see the correct behavior: the counter incrementing.
Imagine if we didn't return that inner function. What would happen?
(defn app-view [] ;; render fn
(let [counter (r/atom 0)] ;; setup
[:div
[:p @counter]
[:button
{:on-click
(fn [e]
(swap! counter inc))}
"Increment!"]]))
The counter feature would break. Remember: in a Form 2 component, we have an outer function that is run only once and an inner function that is run every time the component re-renders.
When we don't have an inner function, the outer function assumes the role of a render function.
In the example above, this means that app-view
gets re-run every time the component renders. Do you understand the problem now? The component-state is getting re-created with every render. We get a new counter r/atom on each re-render.
If a component does not re-render, it may be because you're re-creating state on every re-render.
Warmly,
DH
Top comments (1)
Great article!