|
116 | 116 | (binding [*current-component* c] |
117 | 117 | (wrap-render c compiler))) |
118 | 118 |
|
| 119 | +;; Ratom cleanup |
| 120 | +;; On StrictMode React calls mount->unmount->mount to |
| 121 | +;; ensure there all start is correctly setup there. |
| 122 | +;; This means we need to use tricks to keep the render ratom |
| 123 | +;; non-disposed when unmount is called on the component |
| 124 | +;; initialization. It we let the dispose to be called, |
| 125 | +;; we lose the ratom watches from derefs inside reagent-render, |
| 126 | +;; and there is no good way to restore them. |
| 127 | + |
| 128 | +(defn cancel-cleanup [^clj component-state] |
| 129 | + (when (.-cleanup-queued component-state) |
| 130 | + (set! (.-cleanup-cancelled component-state) true) |
| 131 | + (set! (.-cleanup-queued component-state) false))) |
| 132 | + |
| 133 | +;; Delay ratom dispose call so it can be cancelled if StrictMode |
| 134 | +;; calls setup the second time. |
| 135 | +(defn queue-cleanup [^clj component-state] |
| 136 | + (set! (.-cleanup-cancelled component-state) false) |
| 137 | + (set! (.-cleanup-queued component-state) true) |
| 138 | + ;; Promise.resolve creates a microtask, vs setTimeout regular task. |
| 139 | + ;; A scheduled microtask runs before the next event loop begings (where a regular task would run). |
| 140 | + (.then (.resolve js/Promise nil) |
| 141 | + (fn [] |
| 142 | + (when (false? (.-cleanup-cancelled component-state)) |
| 143 | + (set! (.-cleanup-queued component-state) false) |
| 144 | + (batch/mark-rendered component-state) |
| 145 | + (some-> (gobj/get component-state "cljsRatom") ratom/dispose!))))) |
119 | 146 |
|
120 | 147 | ;;; Method wrapping |
121 | 148 |
|
|
193 | 220 |
|
194 | 221 | :componentDidMount |
195 | 222 | (fn componentDidMount [] |
196 | | - (this-as c (.call f c c))) |
| 223 | + (this-as c |
| 224 | + (cancel-cleanup c) |
| 225 | + (when-not (nil? f) |
| 226 | + (.call f c c)))) |
197 | 227 |
|
198 | 228 | :componentWillUnmount |
199 | 229 | (fn componentWillUnmount [] |
200 | 230 | (this-as c |
201 | | - (some-> (gobj/get c "cljsRatom") ratom/dispose!) |
202 | | - (batch/mark-rendered c) |
| 231 | + (queue-cleanup c) |
203 | 232 | (when-not (nil? f) |
204 | 233 | (.call f c c)))) |
205 | 234 |
|
|
218 | 247 | ;; Though the value is nil here, the wrapper function will be |
219 | 248 | ;; added to class to manage Reagent ratom lifecycle. |
220 | 249 | (def obligatory {:shouldComponentUpdate nil |
| 250 | + :componentDidMount nil |
221 | 251 | :componentWillUnmount nil}) |
222 | 252 |
|
223 | 253 | (def dash-to-method-name (util/memoize-1 util/dash-to-method-name)) |
|
427 | 457 | ;; FIXME: Access cljsRatom using interop forms |
428 | 458 | rat ^ratom/Reaction (gobj/get reagent-state "cljsRatom")] |
429 | 459 |
|
430 | | - ;; Delay ratom dispose call so it can be cancelled if StrictMode |
431 | | - ;; calls setup the second time. |
432 | 460 | (react/useEffect |
433 | 461 | (fn mount [] |
434 | | - (when (.-cleanup-queued reagent-state) |
435 | | - ;; (js/console.log "cancel cleanup") |
436 | | - (set! (.-cleanup-cancelled reagent-state) true) |
437 | | - (set! (.-cleanup-queued reagent-state) false)) |
| 462 | + (cancel-cleanup reagent-state) |
438 | 463 | (fn unmount [] |
439 | | - ;; (js/console.log "queue cleanup") |
440 | | - (set! (.-cleanup-cancelled reagent-state) false) |
441 | | - (set! (.-cleanup-queued reagent-state) true) |
442 | | - ;; Promise.resolve creates a microtask, vs setTimeout regular task. |
443 | | - ;; A scheduled microtask runs before the next event loop begings (where a regular task would run). |
444 | | - (.then (.resolve js/Promise nil) |
445 | | - (fn [] |
446 | | - (when (false? (.-cleanup-cancelled reagent-state)) |
447 | | - ;; (js/console.log "run cleanup") |
448 | | - (set! (.-cleanup-queued reagent-state) false) |
449 | | - (some-> (gobj/get reagent-state "cljsRatom") ratom/dispose!)))))) |
| 464 | + (queue-cleanup reagent-state))) |
450 | 465 | ;; Ignore props - only run effect once on mount and unmount |
451 | 466 | ;; (which means always twice under the React strict mode). |
452 | 467 | #js []) |
|
0 commit comments