Revisions: use useSubRegistry={false} to fix global store selectors#76152
Revisions: use useSubRegistry={false} to fix global store selectors#76152
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Size Change: +107 B (0%) Total Size: 8.75 MB
ℹ️ View Unchanged
|
Why is there two |
|
Can confirm this fixes the linked issue. Another issue I've noticed on trunk: Code that tries to extend blocks or uses ScreencastHere, you notice that only one block has a note indicator, but it's still rendered when switching between blocks, because the selected CleanShot.2026-03-05.at.16.51.10.mp4 |
|
@ellatrix, do we want to ship this with the 7.0? |
|
Yes, I'll fix the remaining issues and try to merge into one provider. Not sure if tonight or tomorrow morning before Beta 4, though there's some other revision related things that I want to look at that may be more pressing since it involves new UI (block inspector) |
When the revisions canvas takes over the full screen, it should use the
global block-editor store (`useSubRegistry={false}`) rather than creating
an isolated sub-registry. This allows the revision preview to behave like
a new screen/route that fully owns the editor state.
Two issues arise when sharing the store:
1. Settings feedback loop: The canvas reads settings from the store via
`useSelect`, adds `isPreviewMode`, then the provider writes them back
with `__internalIsInitialized`. This triggers the `useSelect` again,
creating an infinite loop. Fixed by capturing settings once on mount
via `useState` initializer instead of reactively.
2. Block sync conflict: Two root-level `useBlockSync` instances (parent
editor + revision canvas) both try to control the same store's blocks.
The parent's subscription would propagate revision blocks back to the
entity as unsaved edits, and on unmount the cleanup would clear the
entity entirely. Fixed by passing `value={undefined}` and noop
handlers to the parent's provider during revisions mode, making its
block sync inert.
Closes #75926
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
0d30d60 to
a5f6379
Compare
|
Flaky tests detected in bb43778. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/23117661809
|
Instead of nesting a second ExperimentalBlockEditorProvider inside
RevisionsCanvas (both with useSubRegistry={false}), swap the props on
the parent provider when in revisions mode. This eliminates the
settings feedback loop and the isPreviewMode leak that left blocks
unselectable after exiting revisions.
- Lift showDiff state to the editor store (reducer, action, selector)
- Extract block preparation into useRevisionBlocks hook
- Feed revision blocks, preview settings, and noop handlers through
the parent BlockEditorProviderComponent
- Simplify RevisionsCanvas to a pure view (diff styles + visual editor)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Regression test for #75926. Registers a block that uses the global wp.data.select('core/block-editor') to find its group parent and verifies it works in revisions mode. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@youknowriad @Mamaduka Ok, I updated this PR to reuse the same provider as the regular editor canvas. How's this? |
| const revisionBlocks = useRevisionBlocks(); | ||
| const blocks = revisionBlocks !== null ? revisionBlocks : entityBlocks; | ||
| const finalSettings = useMemo( | ||
| () => | ||
| isInRevisionsMode | ||
| ? { ...blockEditorSettings, isPreviewMode: true } | ||
| : blockEditorSettings, | ||
| [ isInRevisionsMode, blockEditorSettings ] | ||
| ); |
There was a problem hiding this comment.
Suggestion: could be handled later.
These can probably be absorbed by useBlockEditorSettings and useBlockEditorProps. Maybe we should also make onChangeSelection part of useBlockEditorProps.
There was a problem hiding this comment.
I guess that makes sense
There was a problem hiding this comment.
Leaving selection out for now. I'm actually not sure if that should be synced or not. I guess it will become more clear when we add the block inspector panel.
Mamaduka
left a comment
There was a problem hiding this comment.
This looks good, and we can continue improving and refactoring the code until the next release.
…Props Move isPreviewMode override into useBlockEditorSettings (selecting isRevisionsMode internally) and revision blocks + noop handlers into useBlockEditorProps, simplifying the provider component. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Since the block-editor store is now shared (useSubRegistry=false), blocks are selectable in revisions mode and the block inspector works. Show the Block tab so users can switch between the Revision and Block tabs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… mode Check canEditBlock in BlockStyles, BlockVariationTransforms, and EditContents so they are hidden when blocks are not editable (e.g. in revisions/preview mode). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
There was a conflict while trying to cherry-pick the commit to the wp/7.0 branch. Please resolve the conflict manually and create a PR to the wp/7.0 branch. PRs to wp/7.0 are similar to PRs to trunk, but you should base your PR on the wp/7.0 branch instead of trunk. |
…76152) Co-authored-by: ellatrix <ellatrix@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: pbiron <pbiron@git.wordpress.org>
What?
Closes #75926
Why?
The revisions canvas creates its own
ExperimentalBlockEditorProviderwith a sub-registry. Globalwp.data.select('core/block-editor')calls can't see the revision blocks, so any block using global selectors to find parents or siblings breaks in revisions mode.As noted in #76152 (comment), there's no need for two providers — the parent provider's props can be swapped when entering revisions mode.
How?
useRevisionBlockshook — computes revision blocks (diff or plain parse) in the parent provider. Returnsnullwhen not in revisions mode.value={revisionBlocks},onChange/onInput/onChangeSelection={noop},settings={...settings, isPreviewMode: true}. Otherwise: normal entity blocks and handlers.showDifflifted to editor store — the provider needs it for block preparation, so it moves fromuseStateinEditorInterfaceto a reducer/action/selector.RevisionsCanvassimplified — no more nested provider, block preparation, or settings capture. Just diff styles andVisualEditor.Testing Instructions
🤖 Generated with Claude Code