Notes: Extract floating notes state into a dedicated store#77424
Notes: Extract floating notes state into a dedicated store#77424
Conversation
Extracts the mutable floating-board state (block refs, floating refs, thread heights) out of React hooks and into a plain JS store (`board-store.js`) consumed via `useSyncExternalStore`.
|
Size Change: +47 B (0%) Total Size: 7.75 MB 📦 View Changed
ℹ️ View Unchanged
|
|
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. |
|
Flaky tests detected in de5e15d. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/24507973349
|
t-hamano
left a comment
There was a problem hiding this comment.
Thanks for the PR!
This is a great refactoring, and I learned today that useSyncExternalStore is the optimal choice 😄
It seems the right choice for this type of custom store, plus we're subscribing to extrnal API, so yes. |
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: t-hamano <wildworks@git.wordpress.org>
What?
This is a follow-up to #77414.
Extract the floating notes board state into a dedicated store and remove the manual
reflowCommentsreflow mechanism.Why?
blockRefs,heights) used ReactuseState, causing full re-renders and synchronousgetBoundingClientRectreads inuseEffect. Rapid state updates (typing, resizing, CRUD) across N threads resulted in redundant recalculations on each render cycle.reflowComments(auseReducer-basedDate.now()counter) was used in about 15 places across 6 files to trigger layout recalculation after comment CRUD and textarea resizing. This approach was fragile and triggered more times than needed. Now it's redundant, theResizeObservermonitors panel heights.How?
Board store: A plain JS store (compatible with
useSyncExternalStore) that holdsblockRefs,floatingRefs, andheightsoutside React state. A singleResizeObserverwatches all floating panel elements and emits only when heights actually change.getBlockRects()batches allgetBoundingClientRectreads in one pass.Testing Instructions
Testing Instructions for Keyboard
Same.
Screenshots or screencast
Before - every keystroke triggers reflow
CleanShot.2026-04-16.at.14.59.08.mp4
After - only actual height changes trigger reflow
CleanShot.2026-04-16.at.14.58.30.mp4
Use of AI Tools
Used Claude to brainstorm my ideas, tested and reviewed personally.