Skip to content

Commit

Permalink
ErrorBoundary using shadow.cljs.modern defclass (#255)
Browse files Browse the repository at this point in the history
To work around reagent-project/reagent#581. Enable the functional reagent compiler also for server-side-rendering fixing an error that occurred previously when trying to render a component with hooks.

Co-authored-by: Martin Kavalar <[email protected]>
  • Loading branch information
mhuebert and mk authored Nov 1, 2022
1 parent 3854f46 commit 4059252
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 25 deletions.
8 changes: 2 additions & 6 deletions notebooks/viewers/errrors.clj
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,12 @@
(clerk/with-viewer {:render-fn '(fn [x] (throw (ex-info "I blow up when called" {})))}
:boom)

(clerk/with-viewer {:render-fn '(fn [x] x)}
(clerk/with-viewer {:render-fn '(fn [_] (v/inspect-presented :crash))}
42)

(clerk/with-viewer {:render-fn '(fn [_] (v/inspect :crash))}
42)

(clerk/with-viewer {:render-fn '(fn [_] (v/html (v/inspect :crash)))}
(clerk/with-viewer {:render-fn '(fn [_] (v/html (v/inspect-presented :crash)))}
42)

(clerk/with-viewer {:render-fn '(fn [_] (v/html [1 2 3]))}
42)


2 changes: 1 addition & 1 deletion resources/viewer-js-hash
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3xseeZnVHU7wP8QKdQc1nhsr3Biq
3nPjsVv13n4g6ceiJx6JUk9jjawS
47 changes: 29 additions & 18 deletions src/nextjournal/clerk/render.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
[reagent.core :as r]
[reagent.dom :as rdom]
[reagent.ratom :as ratom]
[shadow.cljs.modern :refer [defclass]]
[sci.core :as sci]))

;; a type for wrapping react/useState to support reset! and swap!
Expand Down Expand Up @@ -100,10 +101,7 @@
#js[x])
#(binding [reagent.ratom/*ratom-context* nil] @x))))

(when (exists? js/window)
;; conditionalized currently because this throws in node
;; TypeError: Cannot assign to read only property 'reagentRender' of object '#<Object>'
(r/set-default-compiler! (r/create-compiler {:function-components true})))
(r/set-default-compiler! (r/create-compiler {:function-components true}))

(declare inspect inspect-presented reagent-viewer html html-viewer)

Expand Down Expand Up @@ -284,19 +282,32 @@
(when-some [data (.-data error)]
[:div.mt-2 [inspect data]])])




(defn error-boundary [!error & _]
(r/create-class
{:constructor (fn [_ _])
:component-did-catch (fn [_ e _info] (reset! !error e))
:get-derived-state-from-error (fn [e] (reset! !error e) #js {})
:reagent-render (fn [_error & children]
(if-let [error @!error]
(error-view error)
[view-context/provide {:!error !error}
(into [:<>] children)]))}))
(def ErrorProvider (j/get (view-context/get-context :!error) :Provider))

(defclass ErrorBoundary
(extends react/Component)
(field !error)
(constructor [this ^js props]

(super props)
(set! !error (j/get props :!error))
(set! (.-state this) #js{:error @!error}))
Object
(componentDidMount [this]
(add-watch !error this
(fn [_ _ _ new-val]
(j/call this :setState #js{:error new-val}))))
(componentWillUnmount [this] (remove-watch !error this))
(render [^js this props]
(j/let [^js {{:keys [error]} :state
{:keys [children]} :props} this]
(if error
(r/as-element [error-view error])
(.apply react/createElement nil
(.concat #js[ErrorProvider #js{:value !error}] children))))))

(j/!set ErrorBoundary
:getDerivedStateFromError (fn [error] #js{:error error}))

(def default-loading-view "Loading...")

Expand Down Expand Up @@ -356,7 +367,7 @@
(reset! !desc (read-result result !error))
(reset! !error nil))
[view-context/provide {:fetch-fn fetch-fn}
[error-boundary !error
[:> ErrorBoundary {:!error !error}
[:div.relative
[:div.overflow-y-hidden
{:ref ref-fn}
Expand Down

0 comments on commit 4059252

Please sign in to comment.