Skip to content

fix: prevent table column insertion from freezing - #985

Merged
petyosi merged 3 commits into
mdx-editor:mainfrom
Bashar-Omar:fix/982-table-column-popover-freeze
Sep 26, 2026
Merged

petyosi merged 3 commits into
mdx-editor:mainfrom
Bashar-Omar:fix/982-table-column-popover-freeze

Conversation

@Bashar-Omar

Copy link
Copy Markdown
Contributor

Fixes #982.

Column insertion was updating the table while the column popover was still in the same interaction. Since inserting a column changes the header geometry, the popover trigger moves while Radix is positioning it and React falls into repeated updates.

This closes the column popover first and defers the Lexical table mutation to the next task. The existing node-by-key guard and focus behavior stay unchanged.

Added browser coverage for inserting columns on both sides. Before the fix, both cases timed out with Maximum update depth exceeded in Chromium, Firefox, and WebKit. After the fix, the full CI suite passes.

@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 4.3.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

pull Bot pushed a commit to LeeeeeeM/editor that referenced this pull request Sep 26, 2026
Since the editor renders decorators through Lexical's extension composer
(useSyncExternalStore), React state set inside parentEditor.update() is
rendered before the new table contents. After a column insert, that
render focused the cell that was about to shift right, and its late
focus event fought the new cell for the active position until React
aborted with "Maximum update depth exceeded" (mdx-editor#982).

Set the active cell from the update's onUpdate callback instead, which
runs after the commit, and replace the setTimeout workaround from mdx-editor#985.
The row and add-row/add-column actions get the same treatment, since they
relied on the same ordering.

Also read the table size from the committed editor state rather than
the lexicalTable prop, which still describes the table from before the
change. Inserting right of the last column or below the last row
previously moved focus to the wrong cell or out of the table.
@petyosi

petyosi commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Thanks for the reproduction and the browser test, @Bashar-Omar. This shipped in v4.3.0, but with a different fix on top of yours, so here is why the setTimeout is no longer in TableEditor.tsx.

While looking into this further, it turned out to be a regression from two earlier changes combined:

  • The editor now renders decorators through Lexical's extension composer, which uses useSyncExternalStore instead of the older flushSync-based decorator hook.
  • A later fix moved setActiveCellWithBoundaries inside parentEditor.update().

With both in place, React rendered the new active cell ([0, 0]) against the old table first and focused the cell that was about to shift right. Its late focus event then claimed the active position back from the new cell, and the two cell editors kept taking focus from each other until React hit "Maximum update depth exceeded". Rows were not affected because <tr> elements are keyed by index, so the shifted cells remount instead of sending stale focus events.

The fix in 5408665 sets the active cell from the update's onUpdate callback, which runs after the commit. That removes the need to defer the mutation or control the popover (it closes on its own once focus moves to the new cell). The same change covers insert row and the add-row/add-column buttons, and it fixes two related bugs: inserting right of the last column or below the last row moved focus to the wrong cell.

Your table-column-insertion.spec.ts is still in place and guards the regression. Thanks again for the contribution!

@Bashar-Omar

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed breakdown. Moving the active-cell update to onUpdate after the Lexical commit makes the ordering issue much clearer than my initial popover hypothesis. Glad the browser regression test was useful, and nice catch on the last-row/last-column focus cases as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Inserting a table column left or right freezes the editor

2 participants