Toggle red div and :embed-app-state
Closed this issue · 2 comments
In most cases, :embed-app-state ...
and (reaction this ...)
behave the same. I argue that in cases where the behaviour differs, e.g. situations involving higher-order components, users never want the behaviour of :embed-app-state
. You should therefore always use (reaction this ...)
.
The following Reacl component hierarchy exemplifies the problem with :embed-app-state
. At (1) we first use a normal div
as a container element for a counter component. We use :embed-app-state
to carry over the counter value. Later, we decide that it’s time for some toggleable redness, so we write a higher-order component daniel-red-div
, which we use as a container in lieu of the simple div
. The counter is now broken, because the counter value is embedded into the app-state of daniel-red-div
, which has no use for it. :embed-app-state
breaks abstractions.
Are there any situations where :embed-app-state
is preferred over explicit reactions?
;; Just wrap children in a red div
(reacl/defclass daniel-red-div
this
[& children]
local-state [red? false]
handle-message
(fn [_]
(reacl/return :local-state (not red?)))
render
(dom/div
(when red?
{:style {:background-color "red"}})
(dom/button
{:onclick (fn [_] (reacl/send-message! this nil))}
"toggle redness")
children))
;; Increment a counter on button click
(reacl/defclass counting-button
this
counter
[]
handle-message
(fn [_]
(reacl/return :app-state (inc counter)))
render
(dom/button
{:onclick (fn [_] (reacl/send-message! this :inc))}
"Inc"))
(reacl/defclass countainer
this
counter
[]
render
(dom/div ;; (1) try daniel-red-div to break the flow of app-state
"Counter: " counter
(counting-button
(reacl/opt :embed-app-state
(fn [_ childs]
childs))
counter)))
(defn get-app-element []
(gdom/getElement "app"))
(reacl/render-component
(get-app-element)
countainer
0)
There is (opt :parent this)
now, which results in the desired behaviour.
So I think we can close this Markus?
Yes