Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block Editor: use shallow memo for prioritized inserter blocks #65737

Merged
merged 2 commits into from
Oct 7, 2024

Conversation

tyxla
Copy link
Member

@tyxla tyxla commented Sep 30, 2024

What?

This PR updates the prioritized inserter blocks prop to utilize the useShallowMemo utility, which considers array length changes.

Why?

This was initially motivated by resolving an error for React Compiler (see #61788):

  83:3  error  React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior  react-compiler/react-compiler

But then, while researching why it was there in the first place, I noticed @ellatrix introduced the memoization in #30311 to reduce extra updates without a stable reference. @jorgefilipecosta took it a step further in #53943 to consider array length changes, but the fix wasn't considered for #50510, which introduced a similar practice for prioritized inserter blocks.

So, in this PR, we're making the same improvement for prioritizedInserterBlocks while getting rid of the extra eslint-ignore directive.

How?

We're utilizing useShallowMemo for prioritizedInserterBlocks.

Testing Instructions

  • Insert a "Navigation" block.
  • Click the inserter inside the "Navigation" block.
  • Click "Add block" at the bottom.
  • Verify the "Page Link" and "Custom Link" appear first, followed by the rest of the allowed blocks.
  • Verify all tests pass.

Testing Instructions for Keyboard

Same

Screenshots or screencast

Screenshot 2024-09-30 at 13 35 44

@tyxla tyxla added [Type] Enhancement A suggestion for improvement. [Feature] Inserter The main way to insert blocks using the + button in the editing interface [Feature] Nested / Inner Blocks Anything related to the experience of nested/inner blocks inside a larger container, like Group or P [Package] Block editor /packages/block-editor labels Sep 30, 2024
@tyxla tyxla self-assigned this Sep 30, 2024
@tyxla tyxla requested a review from ellatrix as a code owner September 30, 2024 10:41
Copy link

github-actions bot commented Sep 30, 2024

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: tyxla <[email protected]>
Co-authored-by: jsnajdr <[email protected]>
Co-authored-by: DaniGuardiola <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: mirka <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link

github-actions bot commented Sep 30, 2024

Size Change: +344 B (+0.02%)

Total Size: 1.77 MB

Filename Size Change
build/block-editor/index.min.js 256 kB -127 B (-0.05%)
build/block-editor/style-rtl.css 15.4 kB -104 B (-0.67%)
build/block-editor/style.css 15.4 kB -105 B (-0.68%)
build/block-library/blocks/buttons/style-rtl.css 345 B +17 B (+5.18%) 🔍
build/block-library/blocks/buttons/style.css 345 B +17 B (+5.18%) 🔍
build/block-library/blocks/social-links/editor-rtl.css 729 B -28 B (-3.7%)
build/block-library/blocks/social-links/editor.css 727 B -29 B (-3.84%)
build/block-library/editor-rtl.css 11.7 kB -34 B (-0.29%)
build/block-library/editor.css 11.7 kB -35 B (-0.3%)
build/block-library/index.min.js 219 kB -62 B (-0.03%)
build/block-library/style-rtl.css 14.9 kB +3 B (+0.02%)
build/block-library/style.css 14.9 kB +3 B (+0.02%)
build/blocks/index.min.js 52.5 kB -38 B (-0.07%)
build/components/index.min.js 226 kB +779 B (+0.35%)
build/edit-post/index.min.js 13.6 kB +5 B (+0.04%)
build/edit-site/index.min.js 217 kB +25 B (+0.01%)
build/edit-site/posts-rtl.css 7.31 kB +2 B (+0.03%)
build/edit-site/posts.css 7.32 kB +2 B (+0.03%)
build/edit-site/style-rtl.css 12.6 kB +22 B (+0.17%)
build/edit-site/style.css 12.6 kB +22 B (+0.17%)
build/editor/index.min.js 103 kB +17 B (+0.02%)
build/patterns/index.min.js 7.34 kB -2 B (-0.03%)
build/preferences/index.min.js 2.9 kB -6 B (-0.21%)
ℹ️ View Unchanged
Filename Size
build-module/a11y/index.min.js 482 B
build-module/block-library/file/view.min.js 447 B
build-module/block-library/image/view.min.js 1.78 kB
build-module/block-library/navigation/view.min.js 1.16 kB
build-module/block-library/query/view.min.js 743 B
build-module/block-library/search/view.min.js 616 B
build-module/interactivity-router/index.min.js 3 kB
build-module/interactivity/debug.min.js 16.7 kB
build-module/interactivity/index.min.js 13.4 kB
build/a11y/index.min.js 952 B
build/annotations/index.min.js 2.26 kB
build/api-fetch/index.min.js 2.32 kB
build/autop/index.min.js 2.12 kB
build/blob/index.min.js 579 B
build/block-directory/index.min.js 7.26 kB
build/block-directory/style-rtl.css 1.07 kB
build/block-directory/style.css 1.07 kB
build/block-editor/content-rtl.css 4.46 kB
build/block-editor/content.css 4.46 kB
build/block-editor/default-editor-styles-rtl.css 394 B
build/block-editor/default-editor-styles.css 394 B
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 90 B
build/block-library/blocks/archives/style.css 90 B
build/block-library/blocks/audio/editor-rtl.css 149 B
build/block-library/blocks/audio/editor.css 151 B
build/block-library/blocks/audio/style-rtl.css 132 B
build/block-library/blocks/audio/style.css 132 B
build/block-library/blocks/audio/theme-rtl.css 134 B
build/block-library/blocks/audio/theme.css 134 B
build/block-library/blocks/avatar/editor-rtl.css 115 B
build/block-library/blocks/avatar/editor.css 115 B
build/block-library/blocks/avatar/style-rtl.css 104 B
build/block-library/blocks/avatar/style.css 104 B
build/block-library/blocks/button/editor-rtl.css 265 B
build/block-library/blocks/button/editor.css 265 B
build/block-library/blocks/button/style-rtl.css 538 B
build/block-library/blocks/button/style.css 538 B
build/block-library/blocks/buttons/editor-rtl.css 291 B
build/block-library/blocks/buttons/editor.css 291 B
build/block-library/blocks/calendar/style-rtl.css 240 B
build/block-library/blocks/calendar/style.css 240 B
build/block-library/blocks/categories/editor-rtl.css 132 B
build/block-library/blocks/categories/editor.css 131 B
build/block-library/blocks/categories/style-rtl.css 152 B
build/block-library/blocks/categories/style.css 152 B
build/block-library/blocks/code/editor-rtl.css 53 B
build/block-library/blocks/code/editor.css 53 B
build/block-library/blocks/code/style-rtl.css 121 B
build/block-library/blocks/code/style.css 121 B
build/block-library/blocks/code/theme-rtl.css 122 B
build/block-library/blocks/code/theme.css 122 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 420 B
build/block-library/blocks/columns/style.css 420 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 124 B
build/block-library/blocks/comment-author-avatar/editor.css 124 B
build/block-library/blocks/comment-author-name/style-rtl.css 72 B
build/block-library/blocks/comment-author-name/style.css 72 B
build/block-library/blocks/comment-content/style-rtl.css 120 B
build/block-library/blocks/comment-content/style.css 120 B
build/block-library/blocks/comment-date/style-rtl.css 65 B
build/block-library/blocks/comment-date/style.css 65 B
build/block-library/blocks/comment-edit-link/style-rtl.css 70 B
build/block-library/blocks/comment-edit-link/style.css 70 B
build/block-library/blocks/comment-reply-link/style-rtl.css 71 B
build/block-library/blocks/comment-reply-link/style.css 71 B
build/block-library/blocks/comment-template/style-rtl.css 200 B
build/block-library/blocks/comment-template/style.css 199 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 228 B
build/block-library/blocks/comments-pagination/editor.css 217 B
build/block-library/blocks/comments-pagination/style-rtl.css 234 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-title/editor-rtl.css 75 B
build/block-library/blocks/comments-title/editor.css 75 B
build/block-library/blocks/comments/editor-rtl.css 832 B
build/block-library/blocks/comments/editor.css 832 B
build/block-library/blocks/comments/style-rtl.css 632 B
build/block-library/blocks/comments/style.css 631 B
build/block-library/blocks/cover/editor-rtl.css 641 B
build/block-library/blocks/cover/editor.css 642 B
build/block-library/blocks/cover/style-rtl.css 1.62 kB
build/block-library/blocks/cover/style.css 1.6 kB
build/block-library/blocks/details/editor-rtl.css 65 B
build/block-library/blocks/details/editor.css 65 B
build/block-library/blocks/details/style-rtl.css 86 B
build/block-library/blocks/details/style.css 86 B
build/block-library/blocks/embed/editor-rtl.css 331 B
build/block-library/blocks/embed/editor.css 331 B
build/block-library/blocks/embed/style-rtl.css 419 B
build/block-library/blocks/embed/style.css 419 B
build/block-library/blocks/embed/theme-rtl.css 133 B
build/block-library/blocks/embed/theme.css 133 B
build/block-library/blocks/file/editor-rtl.css 326 B
build/block-library/blocks/file/editor.css 326 B
build/block-library/blocks/file/style-rtl.css 278 B
build/block-library/blocks/file/style.css 279 B
build/block-library/blocks/file/view.min.js 324 B
build/block-library/blocks/footnotes/style-rtl.css 198 B
build/block-library/blocks/footnotes/style.css 197 B
build/block-library/blocks/form-input/editor-rtl.css 229 B
build/block-library/blocks/form-input/editor.css 229 B
build/block-library/blocks/form-input/style-rtl.css 357 B
build/block-library/blocks/form-input/style.css 357 B
build/block-library/blocks/form-submission-notification/editor-rtl.css 344 B
build/block-library/blocks/form-submission-notification/editor.css 341 B
build/block-library/blocks/form-submit-button/style-rtl.css 69 B
build/block-library/blocks/form-submit-button/style.css 69 B
build/block-library/blocks/form/view.min.js 470 B
build/block-library/blocks/freeform/editor-rtl.css 2.6 kB
build/block-library/blocks/freeform/editor.css 2.6 kB
build/block-library/blocks/gallery/editor-rtl.css 946 B
build/block-library/blocks/gallery/editor.css 951 B
build/block-library/blocks/gallery/style-rtl.css 1.83 kB
build/block-library/blocks/gallery/style.css 1.82 kB
build/block-library/blocks/gallery/theme-rtl.css 108 B
build/block-library/blocks/gallery/theme.css 108 B
build/block-library/blocks/group/editor-rtl.css 334 B
build/block-library/blocks/group/editor.css 334 B
build/block-library/blocks/group/style-rtl.css 103 B
build/block-library/blocks/group/style.css 103 B
build/block-library/blocks/group/theme-rtl.css 79 B
build/block-library/blocks/group/theme.css 79 B
build/block-library/blocks/heading/style-rtl.css 188 B
build/block-library/blocks/heading/style.css 188 B
build/block-library/blocks/html/editor-rtl.css 346 B
build/block-library/blocks/html/editor.css 347 B
build/block-library/blocks/image/editor-rtl.css 785 B
build/block-library/blocks/image/editor.css 787 B
build/block-library/blocks/image/style-rtl.css 1.59 kB
build/block-library/blocks/image/style.css 1.59 kB
build/block-library/blocks/image/theme-rtl.css 137 B
build/block-library/blocks/image/theme.css 137 B
build/block-library/blocks/image/view.min.js 1.65 kB
build/block-library/blocks/latest-comments/style-rtl.css 355 B
build/block-library/blocks/latest-comments/style.css 354 B
build/block-library/blocks/latest-posts/editor-rtl.css 179 B
build/block-library/blocks/latest-posts/editor.css 179 B
build/block-library/blocks/latest-posts/style-rtl.css 509 B
build/block-library/blocks/latest-posts/style.css 510 B
build/block-library/blocks/list/style-rtl.css 107 B
build/block-library/blocks/list/style.css 107 B
build/block-library/blocks/loginout/style-rtl.css 61 B
build/block-library/blocks/loginout/style.css 61 B
build/block-library/blocks/media-text/editor-rtl.css 321 B
build/block-library/blocks/media-text/editor.css 320 B
build/block-library/blocks/media-text/style-rtl.css 558 B
build/block-library/blocks/media-text/style.css 556 B
build/block-library/blocks/more/editor-rtl.css 427 B
build/block-library/blocks/more/editor.css 427 B
build/block-library/blocks/navigation-link/editor-rtl.css 644 B
build/block-library/blocks/navigation-link/editor.css 645 B
build/block-library/blocks/navigation-link/style-rtl.css 192 B
build/block-library/blocks/navigation-link/style.css 191 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 295 B
build/block-library/blocks/navigation-submenu/editor.css 294 B
build/block-library/blocks/navigation/editor-rtl.css 2.19 kB
build/block-library/blocks/navigation/editor.css 2.2 kB
build/block-library/blocks/navigation/style-rtl.css 2.25 kB
build/block-library/blocks/navigation/style.css 2.23 kB
build/block-library/blocks/navigation/view.min.js 1.03 kB
build/block-library/blocks/nextpage/editor-rtl.css 392 B
build/block-library/blocks/nextpage/editor.css 392 B
build/block-library/blocks/page-list/editor-rtl.css 378 B
build/block-library/blocks/page-list/editor.css 378 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 B
build/block-library/blocks/paragraph/editor-rtl.css 236 B
build/block-library/blocks/paragraph/editor.css 236 B
build/block-library/blocks/paragraph/style-rtl.css 341 B
build/block-library/blocks/paragraph/style.css 340 B
build/block-library/blocks/post-author-biography/style-rtl.css 74 B
build/block-library/blocks/post-author-biography/style.css 74 B
build/block-library/blocks/post-author-name/style-rtl.css 69 B
build/block-library/blocks/post-author-name/style.css 69 B
build/block-library/blocks/post-author/editor-rtl.css 107 B
build/block-library/blocks/post-author/editor.css 107 B
build/block-library/blocks/post-author/style-rtl.css 188 B
build/block-library/blocks/post-author/style.css 189 B
build/block-library/blocks/post-comments-form/editor-rtl.css 96 B
build/block-library/blocks/post-comments-form/editor.css 96 B
build/block-library/blocks/post-comments-form/style-rtl.css 527 B
build/block-library/blocks/post-comments-form/style.css 528 B
build/block-library/blocks/post-content/editor-rtl.css 74 B
build/block-library/blocks/post-content/editor.css 74 B
build/block-library/blocks/post-content/style-rtl.css 79 B
build/block-library/blocks/post-content/style.css 79 B
build/block-library/blocks/post-date/style-rtl.css 62 B
build/block-library/blocks/post-date/style.css 62 B
build/block-library/blocks/post-excerpt/editor-rtl.css 71 B
build/block-library/blocks/post-excerpt/editor.css 71 B
build/block-library/blocks/post-excerpt/style-rtl.css 155 B
build/block-library/blocks/post-excerpt/style.css 155 B
build/block-library/blocks/post-featured-image/editor-rtl.css 729 B
build/block-library/blocks/post-featured-image/editor.css 726 B
build/block-library/blocks/post-featured-image/style-rtl.css 347 B
build/block-library/blocks/post-featured-image/style.css 347 B
build/block-library/blocks/post-navigation-link/style-rtl.css 215 B
build/block-library/blocks/post-navigation-link/style.css 214 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 399 B
build/block-library/blocks/post-template/style.css 398 B
build/block-library/blocks/post-terms/style-rtl.css 96 B
build/block-library/blocks/post-terms/style.css 96 B
build/block-library/blocks/post-time-to-read/style-rtl.css 70 B
build/block-library/blocks/post-time-to-read/style.css 70 B
build/block-library/blocks/post-title/style-rtl.css 162 B
build/block-library/blocks/post-title/style.css 162 B
build/block-library/blocks/preformatted/style-rtl.css 125 B
build/block-library/blocks/preformatted/style.css 125 B
build/block-library/blocks/pullquote/editor-rtl.css 134 B
build/block-library/blocks/pullquote/editor.css 134 B
build/block-library/blocks/pullquote/style-rtl.css 342 B
build/block-library/blocks/pullquote/style.css 342 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 121 B
build/block-library/blocks/query-pagination-numbers/editor.css 118 B
build/block-library/blocks/query-pagination/editor-rtl.css 154 B
build/block-library/blocks/query-pagination/editor.css 154 B
build/block-library/blocks/query-pagination/style-rtl.css 237 B
build/block-library/blocks/query-pagination/style.css 237 B
build/block-library/blocks/query-title/style-rtl.css 64 B
build/block-library/blocks/query-title/style.css 64 B
build/block-library/blocks/query/editor-rtl.css 452 B
build/block-library/blocks/query/editor.css 451 B
build/block-library/blocks/query/view.min.js 958 B
build/block-library/blocks/quote/style-rtl.css 238 B
build/block-library/blocks/quote/style.css 238 B
build/block-library/blocks/quote/theme-rtl.css 233 B
build/block-library/blocks/quote/theme.css 236 B
build/block-library/blocks/read-more/style-rtl.css 138 B
build/block-library/blocks/read-more/style.css 138 B
build/block-library/blocks/rss/editor-rtl.css 101 B
build/block-library/blocks/rss/editor.css 101 B
build/block-library/blocks/rss/style-rtl.css 288 B
build/block-library/blocks/rss/style.css 287 B
build/block-library/blocks/search/editor-rtl.css 199 B
build/block-library/blocks/search/editor.css 199 B
build/block-library/blocks/search/style-rtl.css 672 B
build/block-library/blocks/search/style.css 671 B
build/block-library/blocks/search/theme-rtl.css 113 B
build/block-library/blocks/search/theme.css 113 B
build/block-library/blocks/search/view.min.js 475 B
build/block-library/blocks/separator/editor-rtl.css 100 B
build/block-library/blocks/separator/editor.css 100 B
build/block-library/blocks/separator/style-rtl.css 248 B
build/block-library/blocks/separator/style.css 248 B
build/block-library/blocks/separator/theme-rtl.css 195 B
build/block-library/blocks/separator/theme.css 195 B
build/block-library/blocks/shortcode/editor-rtl.css 286 B
build/block-library/blocks/shortcode/editor.css 286 B
build/block-library/blocks/site-logo/editor-rtl.css 806 B
build/block-library/blocks/site-logo/editor.css 803 B
build/block-library/blocks/site-logo/style-rtl.css 218 B
build/block-library/blocks/site-logo/style.css 218 B
build/block-library/blocks/site-tagline/editor-rtl.css 87 B
build/block-library/blocks/site-tagline/editor.css 87 B
build/block-library/blocks/site-tagline/style-rtl.css 65 B
build/block-library/blocks/site-tagline/style.css 65 B
build/block-library/blocks/site-title/editor-rtl.css 85 B
build/block-library/blocks/site-title/editor.css 85 B
build/block-library/blocks/site-title/style-rtl.css 143 B
build/block-library/blocks/site-title/style.css 143 B
build/block-library/blocks/social-link/editor-rtl.css 338 B
build/block-library/blocks/social-link/editor.css 338 B
build/block-library/blocks/social-links/style-rtl.css 1.51 kB
build/block-library/blocks/social-links/style.css 1.5 kB
build/block-library/blocks/spacer/editor-rtl.css 346 B
build/block-library/blocks/spacer/editor.css 346 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table-of-contents/style-rtl.css 83 B
build/block-library/blocks/table-of-contents/style.css 83 B
build/block-library/blocks/table/editor-rtl.css 394 B
build/block-library/blocks/table/editor.css 394 B
build/block-library/blocks/table/style-rtl.css 640 B
build/block-library/blocks/table/style.css 639 B
build/block-library/blocks/table/theme-rtl.css 152 B
build/block-library/blocks/table/theme.css 152 B
build/block-library/blocks/tag-cloud/editor-rtl.css 144 B
build/block-library/blocks/tag-cloud/editor.css 144 B
build/block-library/blocks/tag-cloud/style-rtl.css 266 B
build/block-library/blocks/tag-cloud/style.css 265 B
build/block-library/blocks/template-part/editor-rtl.css 368 B
build/block-library/blocks/template-part/editor.css 368 B
build/block-library/blocks/template-part/theme-rtl.css 113 B
build/block-library/blocks/template-part/theme.css 113 B
build/block-library/blocks/term-description/style-rtl.css 126 B
build/block-library/blocks/term-description/style.css 126 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 165 B
build/block-library/blocks/text-columns/style.css 165 B
build/block-library/blocks/verse/style-rtl.css 98 B
build/block-library/blocks/verse/style.css 98 B
build/block-library/blocks/video/editor-rtl.css 396 B
build/block-library/blocks/video/editor.css 397 B
build/block-library/blocks/video/style-rtl.css 192 B
build/block-library/blocks/video/style.css 192 B
build/block-library/blocks/video/theme-rtl.css 134 B
build/block-library/blocks/video/theme.css 134 B
build/block-library/classic-rtl.css 179 B
build/block-library/classic.css 179 B
build/block-library/common-rtl.css 1.1 kB
build/block-library/common.css 1.1 kB
build/block-library/editor-elements-rtl.css 75 B
build/block-library/editor-elements.css 75 B
build/block-library/elements-rtl.css 54 B
build/block-library/elements.css 54 B
build/block-library/reset-rtl.css 472 B
build/block-library/reset.css 472 B
build/block-library/theme-rtl.css 708 B
build/block-library/theme.css 712 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.87 kB
build/commands/index.min.js 16.1 kB
build/commands/style-rtl.css 955 B
build/commands/style.css 952 B
build/components/style-rtl.css 12.3 kB
build/components/style.css 12.3 kB
build/compose/index.min.js 12.7 kB
build/core-commands/index.min.js 3.11 kB
build/core-data/index.min.js 73.4 kB
build/customize-widgets/index.min.js 11 kB
build/customize-widgets/style-rtl.css 1.35 kB
build/customize-widgets/style.css 1.35 kB
build/data-controls/index.min.js 641 B
build/data/index.min.js 8.98 kB
build/date/index.min.js 18 kB
build/deprecated/index.min.js 458 B
build/dom-ready/index.min.js 325 B
build/dom/index.min.js 4.66 kB
build/edit-post/classic-rtl.css 578 B
build/edit-post/classic.css 580 B
build/edit-post/style-rtl.css 2.54 kB
build/edit-post/style.css 2.54 kB
build/edit-widgets/index.min.js 17.8 kB
build/edit-widgets/style-rtl.css 4.19 kB
build/edit-widgets/style.css 4.19 kB
build/editor/style-rtl.css 9.33 kB
build/editor/style.css 9.34 kB
build/element/index.min.js 4.83 kB
build/escape-html/index.min.js 537 B
build/format-library/index.min.js 8.11 kB
build/format-library/style-rtl.css 476 B
build/format-library/style.css 476 B
build/hooks/index.min.js 1.65 kB
build/html-entities/index.min.js 445 B
build/i18n/index.min.js 3.58 kB
build/is-shallow-equal/index.min.js 526 B
build/keyboard-shortcuts/index.min.js 1.31 kB
build/keycodes/index.min.js 1.46 kB
build/list-reusable-blocks/index.min.js 2.19 kB
build/list-reusable-blocks/style-rtl.css 852 B
build/list-reusable-blocks/style.css 852 B
build/media-utils/index.min.js 3.2 kB
build/notices/index.min.js 946 B
build/nux/index.min.js 1.62 kB
build/nux/style-rtl.css 749 B
build/nux/style.css 745 B
build/patterns/style-rtl.css 687 B
build/patterns/style.css 685 B
build/plugins/index.min.js 1.81 kB
build/preferences-persistence/index.min.js 2.06 kB
build/preferences/style-rtl.css 554 B
build/preferences/style.css 554 B
build/primitives/index.min.js 829 B
build/priority-queue/index.min.js 1.54 kB
build/private-apis/index.min.js 1.01 kB
build/react-i18n/index.min.js 630 B
build/react-refresh-entry/index.min.js 9.47 kB
build/react-refresh-runtime/index.min.js 6.76 kB
build/redux-routine/index.min.js 2.69 kB
build/reusable-blocks/index.min.js 2.55 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.1 kB
build/router/index.min.js 1.96 kB
build/server-side-render/index.min.js 1.94 kB
build/shortcode/index.min.js 1.4 kB
build/style-engine/index.min.js 2.04 kB
build/token-list/index.min.js 581 B
build/url/index.min.js 3.9 kB
build/vendors/react-dom.min.js 41.7 kB
build/vendors/react-jsx-runtime.min.js 560 B
build/vendors/react.min.js 4.02 kB
build/viewport/index.min.js 965 B
build/warning/index.min.js 250 B
build/widgets/index.min.js 7.17 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.03 kB

compressed-size-action

const _prioritizedInserterBlocks = useMemo(
() => prioritizedInserterBlocks,
// eslint-disable-next-line react-hooks/exhaustive-deps
const _prioritizedInserterBlocks = useShallowMemo(
Copy link
Member

Choose a reason for hiding this comment

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

It's a good idea to use useShallowMemo here but I think the useShallowMemo utility is not implemented very well. It will do a cascade of setState calls and rerenders. It should be storing the memoized value in a ref instead. Something like:

function useMemoEx( callback, compare ) {
  const memoRef = useRef( undefined );
  const newValue = callback();
  if ( memoRef.current === undefined || ! compare( memoRef.current, newValue ) ) {
    memoRef.current = newValue;
  }
  return memoRef.current;
}

I'm pretty sure we already have such a hook (memo with custom compare) defined somewhere.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a good point 👍

I've seen you working on it in another repository.

Feel free to open a PR, I think it can be improved separately.

Copy link
Contributor

@DaniGuardiola DaniGuardiola Oct 1, 2024

Choose a reason for hiding this comment

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

@jsnajdr the implementation you're proposing is unsafe because you're reading/writing refs in render, which is forbidden by the React Gods (can mess things up in concurrent rendering trees). When doing render-time computations, you simply can't use refs.

However, many use cases for render-time refs can be replaced by derived state, which is a technique consisting of calling a setState at render time, which causes the render function to instantly re-run synchronously, skipping all effects and other work of the kind. This is fine, as long as the state is guaranteed to settle, otherwise it can result in an endless loop. Can't find it right now, but the technique is officially listed somewhere in the official, updated docs.

Running a component's render function is typically pretty much free, so it'd be rare if this technique is a problem for performance. Re-rendering is a tool, not a danger to avoid.

It'd be another story imo if you found a specific perf problem somewhere that is caused by excessive re-rendering, that can happen but anything earlier than that feels like premature optimization (or even worsening, as sometimes re-rendering is the better option).

That's my 2cents anyway :)

Copy link
Member

@Mamaduka Mamaduka Oct 1, 2024

Choose a reason for hiding this comment

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

Some context for the original useShallowMemo - #53943 (comment). We can adopt the usePrevious hook to achieve the same behavior by adding the optional compare as the second argument. But duplication is okay, as usual.

Aside: The usehooks.com has also updated its implementation of usePrevious to use the new pattern.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't agree that breaking the rules to prevent renders without a clear performance issue is the pragmatic and less ideological way, I'd argue it's the opposite. That said, we can agree to disagree on that too :P

Just hope I don't have a "told you so" moment a few months down the line. No hard feelings either way!

Copy link
Member

Choose a reason for hiding this comment

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

In the general case, I do agree that we shouldn't be disobeying the React Gods without a substantial upside, and without a mechanism to catch problems when things start to break. Especially because this seems to be the type of thing where the kinds of bugs that could possibly occur in the future are very subtle.

I'm not privy enough of React internals to assess how much of a special exception this is to the general case. In the general case, just because an official hook adopts an implementation internally right now doesn't necessarily make it safe to imitate in userland. Could they rewrite the internal useMemo implementation without us noticing? Could they add a special safeguard for useMemo that doesn't apply to userland imitations? If there really is no magic and we can confidently answer No to those questions, then sure, maybe this is a special exception. (Unfortunately I cannot confidently answer those questions 😅)

Copy link
Member

Choose a reason for hiding this comment

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

I think it's helpful to try to really understand why exactly reading/writing refs during render can be dangerous. The metaphors about rules written by gods are counterproductive, and also not completely innocent, because they suggest that we're dealing with some revealed truths that are inaccessible to reason. That's not true.

One example of a bad component is this:

function Foo( { value } ) {
  const valueRef = useRef();
  valueRef.current = value;
  return <button onClick={ () => { console.log( valueRef.current ); } } />
}

Here, if you render <Foo value="hello"/>, clicking on the button will print hello. That's good. Now React can start rerendering the tree that contains <Foo />, with another value of the prop, but that render is aborted. It suspends or is interrupted, and the results are thrown away. DOM is not changed and effects are not run. But the valueRef.current = value modification was done and it stays. It's an assignment very similar to calling this.value = ... on a component instance, there is nothing sophisticated about it.

This means that an aborted render of <Foo value="world" /> will actually modify valueRef and clicking on the button will log world. The modification that was not supposed to happen has a material effect on the rendered UI. We can construct many other examples like this where aborted, tentative renders can leak into the active UI. That's why the ref access should be moved into effects, because effects run only when the result of the render was actually commited. Or we should use state, because the state of a committed component is isolated from the state of the tentative render, and the updates are not done directly, but go though a managed queue. Refs are not isolated or managed like this, they are "naked" values.

But not all ref reads/writes are dangerous like this. The React docs contain this example that gives us a first piece of evidence that the rules are not absolute.

function Video() {
  const playerRef = useRef(null);
  if (playerRef.current === null) {
    playerRef.current = new VideoPlayer();
  }
  // ...

Here we read and write a ref during render, but the docs say this is fine!

Normally, writing or reading ref.current during render is not allowed. However, it’s fine in this case because the result is always the same, and the condition only executes during initialization so it’s fully predictable.

Indeed, if a tentative render that's going to be aborted initializes the VideoPlayer, we don't mind, because we would create it the same way anyway. And most of the time the tentative render will find out the VideoPlayer already exists and will do nothing. Nothing bad can happen.

Now let's check if useMemo could also possibly be safe like this. Let's implement useMemo in user space:

function useMemo( create, deps ) {
  const prevState = useRef();
  if ( prevState.current === undefined || ! areDepsEqual( prevState.current[ 1 ], deps ) ) {
    prevState.current = [ create(), deps ];
  }
  return prevState.current[ 0 ];
}

Two things to note here:

  1. The hook's create parameter is always capable to produce a valid return value. And it's constructed from "pure" React values: the props, the state, the context. Also the deps are derived from these "pure" values.
  2. The hook is very skeptical about the value in the prevState ref. Before using it, it carefully verifies that it's valid, i.e., whether it was constructed with the same deps. If some bad value leaked into the prevState ref from an aborted render, this will be detected, the value will be ignored, and will be recalculated from the "pure" create function.

That means that the useMemo hook is resilient against bad values that leak into it from aborted renders. The only thing that the aborted renders can ever achieve is that they invalidate your memoization and force you to recreate it, but the hook will never return a bad value.

That's why the native useMemo hook is safe, and also why a user-space useMemo or useShallowMemo implementation is also safe if done well.

Copy link
Member

Choose a reason for hiding this comment

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

@jsnajdr Thanks for the explanation!

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks y'all for the feedback!

I agree with @jsnajdr and will move to ship this, and will keep an eye in the future.

Copy link
Member

@jsnajdr jsnajdr left a comment

Choose a reason for hiding this comment

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

Approving with the caveat that I'm now a co-author and have a conflict of interest 🙂

Copy link
Contributor

@DaniGuardiola DaniGuardiola left a comment

Choose a reason for hiding this comment

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

As discussed, this code breaks the React rules and exposes us to bugs.

}
return prevValue;
const [ memo ] = useState( createShallowMemo );
return memo( value );
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a side effect here at render time, comparable to reading/writing a ref, which makes this unsafe for concurrency and a future source of tearing.

The only reason this doesn't trigger a React compiler error is that their linter is not accounting for this more obscure way of setting and reading non-stateful values, but it is no different than a ref-based solution and the error applies all the same.

Copy link
Contributor

@DaniGuardiola DaniGuardiola left a comment

Choose a reason for hiding this comment

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

Undoing my blocking review as agreed in the thread above 👍

@tyxla tyxla merged commit 3ab6dde into trunk Oct 7, 2024
82 of 86 checks passed
@tyxla tyxla deleted the update/inner-blocks-prioritized-inserter-blocks-memo branch October 7, 2024 12:17
@github-actions github-actions bot added this to the Gutenberg 19.5 milestone Oct 7, 2024
Copy link
Member

@jorgefilipecosta jorgefilipecosta left a comment

Choose a reason for hiding this comment

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

Reading the discussion on this PR was very insightful thank you @DaniGuardiola, @tyxla, @jsnajdr.

From the functionality point of view this PR was also working as expected 👍

@priethor priethor added [Type] Code Quality Issues or PRs that relate to code quality and removed [Type] Enhancement A suggestion for improvement. labels Oct 23, 2024
karthick-murugan pushed a commit to karthick-murugan/gutenberg that referenced this pull request Nov 13, 2024
…ress#65737)

* Block Editor: use shallow memo for prioritized inserter blocks

* Add single-pass implementation of useShallowMemo

---------

Co-authored-by: Jarda Snajdr <[email protected]>

Co-authored-by: tyxla <[email protected]>
Co-authored-by: jsnajdr <[email protected]>
Co-authored-by: DaniGuardiola <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: mirka <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Inserter The main way to insert blocks using the + button in the editing interface [Feature] Nested / Inner Blocks Anything related to the experience of nested/inner blocks inside a larger container, like Group or P [Package] Block editor /packages/block-editor [Type] Code Quality Issues or PRs that relate to code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants