Based on: https://reactjs.org/docs/error-boundaries.html
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed.
As of React 16, errors that were not caught by any error boundary will result in unmounting of the whole React component tree.
Reagent gives us access to the error boundary features
- Returning true from
:component-did-catch stops
the unmounting behaviour - Set an error flag with
:get-derived-state-from-error
- intended to set state so you can re-render app in “error mode” but could also be used for other recovery strategies
This is an example which seems to work
(defn error-boundary []
(let [*error (r/atom nil)]
(r/create-class
{:get-derived-state-from-error (fn [e] (reset! *error e))
:component-did-catch (fn [_ _ _] true)
:reagent-render (fn [form]
(if @*error
[rn/view {:style {:padding 50}}
[rn/text {:style {:font-size 24 :color "red"}} "Error rendering component. Krell will retry on reload."]
[rn/text {:style {:font-size 12 :color "black"}} (str @*error)]
[rn/text {:style {:font-size 12 :color "black"}} (str (.-componentStack @*error))]]
form))})))
(defn ^:export -main [& args]
(r/as-element [error-boundary [app]]))