From 57951dc43ec0c1dc48da7676bd52a9cb0bcd92f8 Mon Sep 17 00:00:00 2001 From: Matthew Lipski Date: Thu, 4 Jun 2026 10:26:07 +0200 Subject: [PATCH 1/2] Fixed mobile infinite rerender for React blocks --- packages/react/src/schema/ReactBlockSpec.tsx | 33 ++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/packages/react/src/schema/ReactBlockSpec.tsx b/packages/react/src/schema/ReactBlockSpec.tsx index f7e8c49fad..3cf8e05253 100644 --- a/packages/react/src/schema/ReactBlockSpec.tsx +++ b/packages/react/src/schema/ReactBlockSpec.tsx @@ -315,6 +315,39 @@ export function createReactBlockSpec< }, { className: "bn-react-node-view-renderer", + // Any change to a block's content causes ProseMirror to + // re-render the block. On desktop, this change is detected + // using key presses. On mobile, it's instead detected using + // DOM mutations as touchscreen keyboards don't use typical key + // events. However, React's own rendering causes DOM mutations, + // triggering ProseMirror to re-render the block even if the + // mutation is outside the block's editable content. Therefore, + // we need to explicitly ignore mutations outside the block's + // editable content. + ignoreMutation: ({ mutation }) => { + if (mutation.type === "selection") { + return false; + } + + const target = + mutation.target.nodeType === Node.ELEMENT_NODE + ? (mutation.target as HTMLElement) + : mutation.target.parentElement; + const content = target?.closest("[data-node-view-content]"); + + // Ignore mutations outside a block's editable content. + if (!content) { + return true; + } + + // Also ignore mutations for the editable content wrapper + // element. + if (mutation.target === content) { + return true; + } + + return false; + }, }, )(this.props!) as ReturnType; } else { From 1daebc3164a0b320ab691264a73fec4a9738b9c2 Mon Sep 17 00:00:00 2001 From: Matthew Lipski Date: Mon, 8 Jun 2026 18:50:41 +0200 Subject: [PATCH 2/2] Small fix --- packages/react/src/schema/ReactBlockSpec.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/react/src/schema/ReactBlockSpec.tsx b/packages/react/src/schema/ReactBlockSpec.tsx index 3cf8e05253..9df4b5cd27 100644 --- a/packages/react/src/schema/ReactBlockSpec.tsx +++ b/packages/react/src/schema/ReactBlockSpec.tsx @@ -340,9 +340,14 @@ export function createReactBlockSpec< return true; } - // Also ignore mutations for the editable content wrapper - // element. - if (mutation.target === content) { + // Also ignore attribute mutations for the editable content + // wrapper element. These include class names & other + // attributes set via `contentRef`. Other mutations such as + // `childList` are still valid. + if ( + mutation.target === content && + mutation.type === "attributes" + ) { return true; }