🐛 Filter ignorable React removeChild errors at error boundary and fix HTML anti-pattern (#10145)

* 🐛 Filter ignorable exceptions in error-boundary onError callback

The global uncaught-error-handler already skips NotFoundError/removeChild
and other harmless errors, but react-error-boundary's onError callback fires
independently of the window.onerror pipeline. This means the error boundary
was still logging these errors and setting last-exception, causing them to
continue appearing in error reports despite being non-actionable.

Add the is-ignorable-exception? check to the error-boundary* onError so
harmless errors are silently ignored, matching the behavior of the global
handler.

* 🐛 Fix dangerouslySetInnerHTML anti-pattern in context-notification

The previous code used dangerouslySetInnerHTML on the same element that
could also contain React children. This is a React anti-pattern that can
cause reconciliation mismatches and lead to removeChild DOMExceptions.

Refactor to use two separate element branches: one for raw HTML injection
and one for normal React children with links.
This commit is contained in:
Andrey Antukh 2026-06-11 16:59:00 +02:00 committed by GitHub
parent b2c7854f5e
commit 5f21ebd08d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 25 additions and 13 deletions

View File

@ -37,8 +37,20 @@
;; If the error is a stale-asset error (cross-build
;; module mismatch), force a hard page reload instead
;; of showing the error page to the user.
(if (errors/stale-asset-error? error)
(cond
(errors/stale-asset-error? error)
(cf/throttled-reload :reason (ex-message error))
;; If the error is known to be harmless (browser
;; extensions, React DOM conflicts, etc.), ignore it
;; silently — the global uncaught-error-handler
;; already does this, but react-error-boundary's
;; onError fires independently of the window.onerror
;; pipeline, so we must also filter here.
(errors/is-ignorable-exception? error)
nil
:else
(do
(set! errors/last-exception error)
(ex/print-throwable error)

View File

@ -54,16 +54,16 @@
;; The content can arrive in markdown format, in these cases
;; we will use the prop is-html to true to indicate it and
;; that the html injection is performed and the necessary css classes are applied.
[:div {:class (stl/css :context-text)
:dangerouslySetInnerHTML (when is-html #js {:__html content})}
(when-not is-html
[:*
content
(when (some? links)
(for [[index link] (d/enumerate links)]
;; TODO Review this component
[:& lb/link-button {:class (stl/css :link)
:on-click (:callback link)
:value (:label link)
:key (dm/str "link-" index)}]))])]])
(if is-html
[:div {:class (stl/css :context-text)
:dangerouslySetInnerHTML #js {:__html content}}]
[:div {:class (stl/css :context-text)}
content
(when (some? links)
(for [[index link] (d/enumerate links)]
;; TODO Review this component
[:& lb/link-button {:class (stl/css :link)
:on-click (:callback link)
:value (:label link)
:key (dm/str "link-" index)}]))])])