You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
DataTable: TableBulkActions re-creates a MutationObserver on document.body every render #8715
DataTable/TableBulkActions.tsx:58-63 runs a useLayoutEffect with no dependency array. Each run calls observeFocusedAction() (:48), which creates a new MutationObserver on element.ownerDocument.body with {childList: true, subtree: true}. So every render of the bulk actions bar disconnects and rebuilds a document-wide observer.
onFocusCapture already calls observeFocusedAction() when focus moves into the bar, so the per-render effect is redundant for focus tracking.
Verified in code but not measured.
Proposed fix
Do one of the following:
Drop the per-render call and rely on onFocusCapture, keeping only an unmount cleanup that disconnects the observer.
Give the effect a dependency such as selectedCount.
recoverFocus() must still run when an action unmounts while focused.
Acceptance criteria
Re-rendering TableBulkActions with unchanged props doesn't create a new MutationObserver.
Focus recovery still works when the focused bulk action is removed. Add or keep a test for this.
One edge case to keep when simplifying the effect: the observer callback captures onFocusReturn from the render where the action was focused.
I focused an action, re-rendered with a new onFocusReturn while selectedCount stayed at 1, then removed the action through its own state update. Current main calls the new callback; both an unmount-only effect and an effect depending only on selectedCount call the old one. A regression test for that sequence would help; keeping the latest callback in a ref is one possible approach.
I checked this at 324b0aa with React 19.2.7 and jsdom 29.1.1. This was an isolated component test with styling and supporting imports mocked, not the full suite or a real browser. Tested with Codex assistance.
Activity
Muguett-DBY commentedon Nov 13, 2026
One edge case to keep when simplifying the effect: the observer callback captures
onFocusReturnfrom the render where the action was focused.I focused an action, re-rendered with a new
onFocusReturnwhileselectedCountstayed at 1, then removed the action through its own state update. Current main calls the new callback; both an unmount-only effect and an effect depending only onselectedCountcall the old one. A regression test for that sequence would help; keeping the latest callback in a ref is one possible approach.I checked this at
324b0aawith React 19.2.7 and jsdom 29.1.1. This was an isolated component test with styling and supporting imports mocked, not the full suite or a real browser. Tested with Codex assistance.