reagent

A minimalistic ClojureScript interface to React.js http://reagent-project.github.io/
wombawomba 2021-04-06T22:42:51.084200Z

So I'm using error boundaries together with hot code reloading when developing with Reagent, and I've noticed that 'triggered' error boundary often don't get refreshed when my code gets reloaded. Is there a way to force them to get re-rendered on reloads?

wombawomba 2021-04-06T22:43:56.085200Z

FWIW I've tried sprinkling calls to force-update-all in my 'on-reload' fn, but to no avail:

(reagent.dom/force-update-all)
  (reagent.dom/render [views/app-root] (.getElementById js/document "app"))
  (reagent.dom/force-update-all)

p-himik 2021-04-07T08:38:53.093100Z

Nice! Yeah, now reading your messages, I realize that I probably have the same problem. And it's just that I've added an "Undo" button to the re-frame app specifically to undo whatever action has led to the error that prevented me from noticing it.

👍 1
p-himik 2021-04-06T22:45:39.085300Z

How exactly does the error boundary code look like?

wombawomba 2021-04-06T22:46:14.085600Z

@p-himik

(defn <error-boundary>
  [& _]
  (let [*info (r/atom nil)]
    (r/create-class
     {:constructor                  (fn [this _props]
                                      (set! (.-state this) #js {:error nil}))
      :component-did-catch          (fn [_this _e info] (reset! *info info))
      :display-name                 "error-boundary"
      :get-derived-state-from-error (fn [error] #js {:error error})
      :render                       (fn [this]
                                      (r/as-element
                                       (if-let [error (.. this -state -error)]
                                         [<error-message>
                                          error
                                          (some-> @*info .-componentStack)]
                                         (into [:<>] (r/children this)))))})))

p-himik 2021-04-06T22:49:07.085800Z

I don't see anything necessarily wrong with it, but try this one. It works perfectly in my case.

(defn component []
  (let [error (reagent/atom nil)]
    (reagent/create-class
      {:component-did-catch
       (fn [_this _e _info])

       :get-derived-state-from-error
       (fn [e]
         (reset! error e)
         #js {})

       :reagent-render
       (fn []
         (if @error
           [error-component @error]
           [main-component]))})))

wombawomba 2021-04-06T22:49:24.086Z

will do

wombawomba 2021-04-06T22:55:32.086200Z

yeah, no go 😞

wombawomba 2021-04-06T22:56:00.086400Z

I'm using shadow-cljs btw... although I don't think this should affect this sort of thing?

p-himik 2021-04-06T22:56:05.086600Z

Hmm. And how exactly do you re-render the app on code reload.

p-himik 2021-04-06T22:56:11.086800Z

I use shadow-cljs as well.

wombawomba 2021-04-06T22:56:57.087Z

I have a fn that looks like

(defn ^:dev/after-load re-init
  "(Re)initializes the state. Called on page load and code reload."
  []
  (log/debug "Re-initing...")
  (effect-handlers/init!)
  (routes/init!)
  (sub-handlers/init!)
  (reagent.dom/force-update-all)
  (reagent.dom/render [views/app-root] (.getElementById js/document "app"))
  (reagent.dom/force-update-all)
  (css/init-static-classes!)
  (set-config!))

wombawomba 2021-04-06T22:57:32.087200Z

wait a second

wombawomba 2021-04-06T22:57:44.087400Z

I think I see something weird in my shadow-cljs config

wombawomba 2021-04-06T23:08:06.087600Z

yeah okay fixing that thing didn't help

wombawomba 2021-04-06T23:10:35.087800Z

my shadow-cljs config is basically

{...
 :build {:app {...
               :modules  {:base {:init-fn site.core/init
                                 :entries [site.core]}}
               :devtools {:after-load  site.core/re-init
                          :loader-mode :script
                          :preloads    [shadow.remote.runtime.cljs.browser]}}}

wombawomba 2021-04-06T23:12:14.088100Z

I just confirmed that init and re-init get called on page load, and re-init gets called on reload

wombawomba 2021-04-06T23:16:46.088300Z

weirdly I have no problems with any other elements not getting reloaded

p-himik 2021-04-06T23:21:43.088500Z

Huh. No clue, sorry.

wombawomba 2021-04-06T23:26:31.088700Z

yeah very strange

wombawomba 2021-04-06T23:26:52.088900Z

I'm gonna take another look at my init code to see if there's anything weird

wombawomba 2021-04-06T23:27:04.089100Z

perhaps I'm getting my re-frame effects mixed up

p-himik 2021-04-06T23:31:19.089300Z

Now that you mention re-frame - do you really store *info in a ratom or was it just to replace some subscription?