Let's say I have a component defined like this:
(defn test-comp
[timespan-ratom]
(let [[timespan-lower timespan-upper] @timespan-ratom]
(fn []
[:div.row (str "Testing" timespan-lower timespan-upper)])))
timespan-ratom
is defined globally in the component that instantiates test-comp
like this:
(def timespan-ratom (ratom nil))
It's instantiated like this:
[test-comp timespan-ratom]
The first time the timespan-ratom
is used to create test-comp
"Testing" will be printed with the correct timespan-lower
and timespan-upper
value. But when the timespan-ratom
is reset (reset!
) the values are not updated in the test-comp
component? Why is this?
It works when I change the function to this:
(defn test-comp
[timespan-ratom]
(fn []
[:div.row (str "Testing" (first @timespan-ratom) (second @timespan-ratom))]))
Now the reason why I can't simply do like this is that in my actual production code I have local ratom that is dependent on the value of the timespan-ratom
:
(defn test-comp
[timespan-ratom]
(let [[timespan-lower timespan-upper] @timespan-ratom
selected-time (ratom timespan-upper)]
(fn []
,,,)))
I.e. the initial value of selected-time
should be the timespan-upper
value defined by the timespan-ratom
. The selected-time
ratom is then changed locally from the test-comp
component.
How can I solve this?
Remove the inner function nesting from
test-comp
:When you use an inner function with no arguments, the component can never receive the updated ratom, so it will forever hold on to the first value it got from the ratom on the first render. Also, you don't need the inner function here, because you don't have any local state.
If you do have local state (some state that needs to be remembered over the lifetime of the component), update your component so the inner function has the same arguments as the outer function and dereference the atom in the inner function: