Skip to content

Fix rendering issues when both chunking and React's strict mode are enabled#5988

Merged
dylans merged 1 commit intoianstormtaylor:mainfrom
12joan:fix/chunking-broken-in-strict-mode
Dec 16, 2025
Merged

Fix rendering issues when both chunking and React's strict mode are enabled#5988
dylans merged 1 commit intoianstormtaylor:mainfrom
12joan:fix/chunking-broken-in-strict-mode

Conversation

@12joan
Copy link
Contributor

@12joan 12joan commented Dec 10, 2025

Description
If React's strict mode and the experimental chunking optimisation are both enabled, this caused rendering issues inside chunks that prevented slate-react from synchronising changes to the editor value with the DOM. This PR resolves these issues by adjusting the timing of when the chunk tree's modifiedChunks set is cleared.

Example
Recording of the bug as reported by z2devil on Slack:

When the editor chunk is initialized in React StrictMode, text input inside this chunk stops working and the cursor disappears.

20251210170131.mp4

Context
The chunking optimisation works by iteratively mutating a nested "chunk tree" object as part of useChildren every time the parent element renders. On each iteration, the new children array is "reconciled" with the chunk tree, analogous to how React reconciles the DOM with its virtual DOM. This reconciliation can result in chunks being added, removed or modified.

Since each individual chunk in the chunk tree is mutable, React cannot automatically determine whether the component corresponding to each chunk needs to be re-rendered. For this reason, the chunk tree maintains a set of modifiedChunks, which are chunks that have been modified since the last render. If a given chunk appears in this set, we bypass React's memoisation and re-render the chunk's component.

Prior to this PR, this modifiedChunks set was cleared at the start of each iteration (i.e. at the start of each render), so that the set included only those chunks that were modified as part of the current iteration. However, this caused issues with React's strict mode, in which each component's render function is called twice prior to that component actually being rendered.

This meant that on the first render pass, modifiedChunks was correct but unused. On the second render pass (caused by strict mode), modifiedChunks had already been cleared, and the chunk tree had already been updated. This meant that modifiedChunk was empty when React.memo checked whether each chunk component needed to be re-rendered, resulting in the chunk component failing to update in response to changes to the editor value.

This PR fixes this by only clearing modifiedChunks inside a useEffect, by which time its value has already been used.

Checks

  • The new code matches the existing patterns and styles.
  • The tests pass with yarn test.
  • The linter passes with yarn lint. (Fix errors with yarn fix.)
  • The relevant examples still work. (Run examples with yarn start.)
  • You've added a changeset if changing functionality. (Add one with yarn changeset add.)

@changeset-bot
Copy link

changeset-bot bot commented Dec 10, 2025

🦋 Changeset detected

Latest commit: 32d56dd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
slate-react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

'chunk'
),
showSelectedHeadings: parseBoolean('selected_headings', false),
strictMode: parseBoolean('strict', false),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds a checkbox to the huge document example to enable strict mode for testing. Due to the nature of strict mode, this only works when running the examples locally.

image

Copy link
Contributor Author

@12joan 12joan Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file was changed as a result of yarn tsc:examples

@dylans dylans merged commit bfa5055 into ianstormtaylor:main Dec 16, 2025
11 checks passed
This was referenced Dec 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants