-
Notifications
You must be signed in to change notification settings - Fork 412
Description
Running with React strict mode (enabled at the top-level component), React effects are cycled one extra time, which causes functional components created using reagent.impl.component.functional-render
to dispose of their watched values, and not watch them anymore.
The effect defined in functional-render
should provide a symmetrical action to ratom/dispose!
in its first part, in the mount
function.
In my preliminary tests, I have extended the Reaction
type for the following two methods:
(_snapshot [_this]
[state watching auto-run])
(_restore [this [s w a]]
(set! watching w)
(set! state s)
(set! auto-run a)
(set! dirty? true)
(doseq [watcher (set w)]
(-add-watch watcher this handle-reaction-change)))
and used them to save the related values of the Reaction in a new Javascript field between the cleanup and second run of the effect, like this:
(react/useEffect
(fn mount []
(when-some [reagent-state (.-current state-ref)]
(when-some [r-argv (gobj/get reagent-state "ratomSnapshot" nil)]
(let [rat (gobj/get reagent-state "cljsRatom")]
(._restore rat r-argv)
(gobj/remove reagent-state "ratomSnapshot"))))
(fn unmount []
(when-some [rat ^ratom/Reaction (gobj/get reagent-state "cljsRatom")]
(gobj/set reagent-state "ratomSnapshot" (._snapshot rat)))
(some-> (gobj/get reagent-state "cljsRatom") ratom/dispose!)
))
;; Ignore props - only run effect once on mount and unmount
;; (which means always twice under the React strict mode).
#js [])
That solved the issue I have described here, although I still see failures in expanding seqs rendered by these functional components -- but I will be filing that as a separate issue when I gain more understanding of what's going wrong there.