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

Upgrade React packages to v18 #45235

Merged
merged 37 commits into from Dec 1, 2022
Merged

Upgrade React packages to v18 #45235

merged 37 commits into from Dec 1, 2022

Conversation

jsnajdr
Copy link
Member

@jsnajdr jsnajdr commented Oct 24, 2022

Subset of #32765 that only upgrades the React packages, and does no other changes. I'd like to see which e2e tests etc are failing on the latest trunk.

@jsnajdr jsnajdr self-assigned this Oct 24, 2022
@github-actions
Copy link

github-actions bot commented Oct 24, 2022

Size Change: +1.97 kB (0%)

Total Size: 1.32 MB

Filename Size Change
build/block-editor/index.min.js 180 kB -72 B (0%)
build/components/index.min.js 203 kB -902 B (0%)
build/vendors/react-dom.min.js 41.8 kB +3.26 kB (+8%) 🔍
build/vendors/react.min.js 4.02 kB -317 B (-7%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/annotations/index.min.js 2.78 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 487 B
build/block-directory/index.min.js 7.16 kB
build/block-directory/style-rtl.css 1.03 kB
build/block-directory/style.css 1.04 kB
build/block-editor/content-rtl.css 2.71 kB
build/block-editor/content.css 2.71 kB
build/block-editor/default-editor-styles-rtl.css 401 B
build/block-editor/default-editor-styles.css 401 B
build/block-editor/style-rtl.css 14.5 kB
build/block-editor/style.css 14.5 kB
build/block-library/blocks/archives/editor-rtl.css 107 B
build/block-library/blocks/archives/editor.css 106 B
build/block-library/blocks/archives/style-rtl.css 129 B
build/block-library/blocks/archives/style.css 129 B
build/block-library/blocks/audio/editor-rtl.css 185 B
build/block-library/blocks/audio/editor.css 185 B
build/block-library/blocks/audio/style-rtl.css 158 B
build/block-library/blocks/audio/style.css 158 B
build/block-library/blocks/audio/theme-rtl.css 172 B
build/block-library/blocks/audio/theme.css 172 B
build/block-library/blocks/avatar/editor-rtl.css 154 B
build/block-library/blocks/avatar/editor.css 154 B
build/block-library/blocks/avatar/style-rtl.css 126 B
build/block-library/blocks/avatar/style.css 126 B
build/block-library/blocks/block/editor-rtl.css 338 B
build/block-library/blocks/block/editor.css 338 B
build/block-library/blocks/button/editor-rtl.css 517 B
build/block-library/blocks/button/editor.css 517 B
build/block-library/blocks/button/style-rtl.css 566 B
build/block-library/blocks/button/style.css 566 B
build/block-library/blocks/buttons/editor-rtl.css 373 B
build/block-library/blocks/buttons/editor.css 373 B
build/block-library/blocks/buttons/style-rtl.css 368 B
build/block-library/blocks/buttons/style.css 368 B
build/block-library/blocks/calendar/style-rtl.css 270 B
build/block-library/blocks/calendar/style.css 270 B
build/block-library/blocks/categories/editor-rtl.css 125 B
build/block-library/blocks/categories/editor.css 124 B
build/block-library/blocks/categories/style-rtl.css 138 B
build/block-library/blocks/categories/style.css 138 B
build/block-library/blocks/code/editor-rtl.css 102 B
build/block-library/blocks/code/editor.css 102 B
build/block-library/blocks/code/style-rtl.css 159 B
build/block-library/blocks/code/style.css 159 B
build/block-library/blocks/code/theme-rtl.css 160 B
build/block-library/blocks/code/theme.css 160 B
build/block-library/blocks/columns/editor-rtl.css 147 B
build/block-library/blocks/columns/editor.css 147 B
build/block-library/blocks/columns/style-rtl.css 442 B
build/block-library/blocks/columns/style.css 442 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 163 B
build/block-library/blocks/comment-author-avatar/editor.css 163 B
build/block-library/blocks/comment-content/style-rtl.css 134 B
build/block-library/blocks/comment-content/style.css 134 B
build/block-library/blocks/comment-template/style-rtl.css 237 B
build/block-library/blocks/comment-template/style.css 236 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 159 B
build/block-library/blocks/comments-pagination-numbers/editor.css 157 B
build/block-library/blocks/comments-pagination/editor-rtl.css 258 B
build/block-library/blocks/comments-pagination/editor.css 249 B
build/block-library/blocks/comments-pagination/style-rtl.css 272 B
build/block-library/blocks/comments-pagination/style.css 268 B
build/block-library/blocks/comments-title/editor-rtl.css 118 B
build/block-library/blocks/comments-title/editor.css 118 B
build/block-library/blocks/comments/editor-rtl.css 875 B
build/block-library/blocks/comments/editor.css 874 B
build/block-library/blocks/comments/style-rtl.css 672 B
build/block-library/blocks/comments/style.css 671 B
build/block-library/blocks/cover/editor-rtl.css 646 B
build/block-library/blocks/cover/editor.css 647 B
build/block-library/blocks/cover/style-rtl.css 1.61 kB
build/block-library/blocks/cover/style.css 1.6 kB
build/block-library/blocks/embed/editor-rtl.css 327 B
build/block-library/blocks/embed/editor.css 327 B
build/block-library/blocks/embed/style-rtl.css 446 B
build/block-library/blocks/embed/style.css 446 B
build/block-library/blocks/embed/theme-rtl.css 172 B
build/block-library/blocks/embed/theme.css 172 B
build/block-library/blocks/file/editor-rtl.css 335 B
build/block-library/blocks/file/editor.css 335 B
build/block-library/blocks/file/style-rtl.css 288 B
build/block-library/blocks/file/style.css 288 B
build/block-library/blocks/file/view.min.js 353 B
build/block-library/blocks/freeform/editor-rtl.css 2.47 kB
build/block-library/blocks/freeform/editor.css 2.47 kB
build/block-library/blocks/gallery/editor-rtl.css 987 B
build/block-library/blocks/gallery/editor.css 993 B
build/block-library/blocks/gallery/style-rtl.css 1.58 kB
build/block-library/blocks/gallery/style.css 1.58 kB
build/block-library/blocks/gallery/theme-rtl.css 157 B
build/block-library/blocks/gallery/theme.css 157 B
build/block-library/blocks/group/editor-rtl.css 687 B
build/block-library/blocks/group/editor.css 687 B
build/block-library/blocks/group/style-rtl.css 105 B
build/block-library/blocks/group/style.css 105 B
build/block-library/blocks/group/theme-rtl.css 125 B
build/block-library/blocks/group/theme.css 125 B
build/block-library/blocks/heading/style-rtl.css 128 B
build/block-library/blocks/heading/style.css 128 B
build/block-library/blocks/html/editor-rtl.css 365 B
build/block-library/blocks/html/editor.css 366 B
build/block-library/blocks/image/editor-rtl.css 861 B
build/block-library/blocks/image/editor.css 859 B
build/block-library/blocks/image/style-rtl.css 662 B
build/block-library/blocks/image/style.css 666 B
build/block-library/blocks/image/theme-rtl.css 172 B
build/block-library/blocks/image/theme.css 172 B
build/block-library/blocks/latest-comments/style-rtl.css 333 B
build/block-library/blocks/latest-comments/style.css 333 B
build/block-library/blocks/latest-posts/editor-rtl.css 250 B
build/block-library/blocks/latest-posts/editor.css 249 B
build/block-library/blocks/latest-posts/style-rtl.css 514 B
build/block-library/blocks/latest-posts/style.css 514 B
build/block-library/blocks/list/style-rtl.css 135 B
build/block-library/blocks/list/style.css 135 B
build/block-library/blocks/media-text/editor-rtl.css 300 B
build/block-library/blocks/media-text/editor.css 298 B
build/block-library/blocks/media-text/style-rtl.css 540 B
build/block-library/blocks/media-text/style.css 539 B
build/block-library/blocks/more/editor-rtl.css 465 B
build/block-library/blocks/more/editor.css 465 B
build/block-library/blocks/navigation-link/editor-rtl.css 746 B
build/block-library/blocks/navigation-link/editor.css 744 B
build/block-library/blocks/navigation-link/style-rtl.css 153 B
build/block-library/blocks/navigation-link/style.css 153 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 333 B
build/block-library/blocks/navigation-submenu/editor.css 333 B
build/block-library/blocks/navigation/editor-rtl.css 2.19 kB
build/block-library/blocks/navigation/editor.css 2.19 kB
build/block-library/blocks/navigation/style-rtl.css 2.26 kB
build/block-library/blocks/navigation/style.css 2.25 kB
build/block-library/blocks/navigation/view-modal.min.js 2.81 kB
build/block-library/blocks/navigation/view.min.js 447 B
build/block-library/blocks/nextpage/editor-rtl.css 428 B
build/block-library/blocks/nextpage/editor.css 428 B
build/block-library/blocks/page-list/editor-rtl.css 397 B
build/block-library/blocks/page-list/editor.css 398 B
build/block-library/blocks/page-list/style-rtl.css 212 B
build/block-library/blocks/page-list/style.css 212 B
build/block-library/blocks/paragraph/editor-rtl.css 214 B
build/block-library/blocks/paragraph/editor.css 214 B
build/block-library/blocks/paragraph/style-rtl.css 321 B
build/block-library/blocks/paragraph/style.css 321 B
build/block-library/blocks/post-author/style-rtl.css 212 B
build/block-library/blocks/post-author/style.css 212 B
build/block-library/blocks/post-comments-form/editor-rtl.css 137 B
build/block-library/blocks/post-comments-form/editor.css 137 B
build/block-library/blocks/post-comments-form/style-rtl.css 536 B
build/block-library/blocks/post-comments-form/style.css 537 B
build/block-library/blocks/post-date/style-rtl.css 107 B
build/block-library/blocks/post-date/style.css 107 B
build/block-library/blocks/post-excerpt/editor-rtl.css 119 B
build/block-library/blocks/post-excerpt/editor.css 119 B
build/block-library/blocks/post-excerpt/style-rtl.css 116 B
build/block-library/blocks/post-excerpt/style.css 116 B
build/block-library/blocks/post-featured-image/editor-rtl.css 620 B
build/block-library/blocks/post-featured-image/editor.css 618 B
build/block-library/blocks/post-featured-image/style-rtl.css 349 B
build/block-library/blocks/post-featured-image/style.css 349 B
build/block-library/blocks/post-navigation-link/style-rtl.css 190 B
build/block-library/blocks/post-navigation-link/style.css 189 B
build/block-library/blocks/post-template/editor-rtl.css 140 B
build/block-library/blocks/post-template/editor.css 139 B
build/block-library/blocks/post-template/style-rtl.css 317 B
build/block-library/blocks/post-template/style.css 317 B
build/block-library/blocks/post-terms/style-rtl.css 136 B
build/block-library/blocks/post-terms/style.css 136 B
build/block-library/blocks/post-title/style-rtl.css 138 B
build/block-library/blocks/post-title/style.css 138 B
build/block-library/blocks/preformatted/style-rtl.css 139 B
build/block-library/blocks/preformatted/style.css 139 B
build/block-library/blocks/pullquote/editor-rtl.css 170 B
build/block-library/blocks/pullquote/editor.css 170 B
build/block-library/blocks/pullquote/style-rtl.css 357 B
build/block-library/blocks/pullquote/style.css 357 B
build/block-library/blocks/pullquote/theme-rtl.css 201 B
build/block-library/blocks/pullquote/theme.css 201 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 158 B
build/block-library/blocks/query-pagination-numbers/editor.css 156 B
build/block-library/blocks/query-pagination/editor-rtl.css 258 B
build/block-library/blocks/query-pagination/editor.css 247 B
build/block-library/blocks/query-pagination/style-rtl.css 326 B
build/block-library/blocks/query-pagination/style.css 322 B
build/block-library/blocks/query-title/style-rtl.css 108 B
build/block-library/blocks/query-title/style.css 108 B
build/block-library/blocks/query/editor-rtl.css 475 B
build/block-library/blocks/query/editor.css 477 B
build/block-library/blocks/quote/style-rtl.css 253 B
build/block-library/blocks/quote/style.css 253 B
build/block-library/blocks/quote/theme-rtl.css 255 B
build/block-library/blocks/quote/theme.css 259 B
build/block-library/blocks/read-more/style-rtl.css 168 B
build/block-library/blocks/read-more/style.css 168 B
build/block-library/blocks/rss/editor-rtl.css 239 B
build/block-library/blocks/rss/editor.css 240 B
build/block-library/blocks/rss/style-rtl.css 323 B
build/block-library/blocks/rss/style.css 323 B
build/block-library/blocks/search/editor-rtl.css 205 B
build/block-library/blocks/search/editor.css 205 B
build/block-library/blocks/search/style-rtl.css 441 B
build/block-library/blocks/search/style.css 439 B
build/block-library/blocks/search/theme-rtl.css 149 B
build/block-library/blocks/search/theme.css 149 B
build/block-library/blocks/separator/editor-rtl.css 184 B
build/block-library/blocks/separator/editor.css 184 B
build/block-library/blocks/separator/style-rtl.css 269 B
build/block-library/blocks/separator/style.css 269 B
build/block-library/blocks/separator/theme-rtl.css 229 B
build/block-library/blocks/separator/theme.css 229 B
build/block-library/blocks/shortcode/editor-rtl.css 508 B
build/block-library/blocks/shortcode/editor.css 508 B
build/block-library/blocks/site-logo/editor-rtl.css 522 B
build/block-library/blocks/site-logo/editor.css 522 B
build/block-library/blocks/site-logo/style-rtl.css 238 B
build/block-library/blocks/site-logo/style.css 238 B
build/block-library/blocks/site-tagline/editor-rtl.css 129 B
build/block-library/blocks/site-tagline/editor.css 129 B
build/block-library/blocks/site-title/editor-rtl.css 155 B
build/block-library/blocks/site-title/editor.css 155 B
build/block-library/blocks/site-title/style-rtl.css 101 B
build/block-library/blocks/site-title/style.css 101 B
build/block-library/blocks/social-link/editor-rtl.css 219 B
build/block-library/blocks/social-link/editor.css 219 B
build/block-library/blocks/social-links/editor-rtl.css 709 B
build/block-library/blocks/social-links/editor.css 708 B
build/block-library/blocks/social-links/style-rtl.css 1.43 kB
build/block-library/blocks/social-links/style.css 1.43 kB
build/block-library/blocks/spacer/editor-rtl.css 372 B
build/block-library/blocks/spacer/editor.css 372 B
build/block-library/blocks/spacer/style-rtl.css 96 B
build/block-library/blocks/spacer/style.css 96 B
build/block-library/blocks/table/editor-rtl.css 547 B
build/block-library/blocks/table/editor.css 547 B
build/block-library/blocks/table/style-rtl.css 670 B
build/block-library/blocks/table/style.css 669 B
build/block-library/blocks/table/theme-rtl.css 220 B
build/block-library/blocks/table/theme.css 220 B
build/block-library/blocks/tag-cloud/style-rtl.css 287 B
build/block-library/blocks/tag-cloud/style.css 288 B
build/block-library/blocks/template-part/editor-rtl.css 436 B
build/block-library/blocks/template-part/editor.css 436 B
build/block-library/blocks/template-part/theme-rtl.css 139 B
build/block-library/blocks/template-part/theme.css 139 B
build/block-library/blocks/text-columns/editor-rtl.css 135 B
build/block-library/blocks/text-columns/editor.css 135 B
build/block-library/blocks/text-columns/style-rtl.css 198 B
build/block-library/blocks/text-columns/style.css 198 B
build/block-library/blocks/verse/style-rtl.css 130 B
build/block-library/blocks/verse/style.css 130 B
build/block-library/blocks/video/editor-rtl.css 720 B
build/block-library/blocks/video/editor.css 723 B
build/block-library/blocks/video/style-rtl.css 218 B
build/block-library/blocks/video/style.css 218 B
build/block-library/blocks/video/theme-rtl.css 171 B
build/block-library/blocks/video/theme.css 171 B
build/block-library/classic-rtl.css 193 B
build/block-library/classic.css 193 B
build/block-library/common-rtl.css 1.05 kB
build/block-library/common.css 1.05 kB
build/block-library/editor-elements-rtl.css 126 B
build/block-library/editor-elements.css 126 B
build/block-library/editor-rtl.css 11.7 kB
build/block-library/editor.css 11.7 kB
build/block-library/elements-rtl.css 105 B
build/block-library/elements.css 105 B
build/block-library/index.min.js 196 kB
build/block-library/reset-rtl.css 514 B
build/block-library/reset.css 514 B
build/block-library/style-rtl.css 12.4 kB
build/block-library/style.css 12.4 kB
build/block-library/theme-rtl.css 749 B
build/block-library/theme.css 753 B
build/block-serialization-default-parser/index.min.js 1.13 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 50 kB
build/components/style-rtl.css 11.6 kB
build/components/style.css 11.6 kB
build/compose/index.min.js 12.3 kB
build/core-data/index.min.js 15.6 kB
build/customize-widgets/index.min.js 11.3 kB
build/customize-widgets/style-rtl.css 1.41 kB
build/customize-widgets/style.css 1.41 kB
build/data-controls/index.min.js 663 B
build/data/index.min.js 8.12 kB
build/date/index.min.js 32.1 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.74 kB
build/edit-navigation/index.min.js 16.2 kB
build/edit-navigation/style-rtl.css 4.08 kB
build/edit-navigation/style.css 4.09 kB
build/edit-post/classic-rtl.css 569 B
build/edit-post/classic.css 570 B
build/edit-post/index.min.js 34.5 kB
build/edit-post/style-rtl.css 7.43 kB
build/edit-post/style.css 7.42 kB
build/edit-site/index.min.js 60.4 kB
build/edit-site/style-rtl.css 8.55 kB
build/edit-site/style.css 8.55 kB
build/edit-widgets/index.min.js 16.7 kB
build/edit-widgets/style-rtl.css 4.44 kB
build/edit-widgets/style.css 4.44 kB
build/editor/index.min.js 44 kB
build/editor/style-rtl.css 3.65 kB
build/editor/style.css 3.64 kB
build/element/index.min.js 4.72 kB
build/escape-html/index.min.js 548 B
build/experiments/index.min.js 882 B
build/format-library/index.min.js 6.96 kB
build/format-library/style-rtl.css 596 B
build/format-library/style.css 596 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.79 kB
build/keycodes/index.min.js 1.86 kB
build/list-reusable-blocks/index.min.js 2.13 kB
build/list-reusable-blocks/style-rtl.css 858 B
build/list-reusable-blocks/style.css 857 B
build/media-utils/index.min.js 2.94 kB
build/notices/index.min.js 977 B
build/nux/index.min.js 2.07 kB
build/nux/style-rtl.css 772 B
build/nux/style.css 768 B
build/plugins/index.min.js 1.95 kB
build/preferences-persistence/index.min.js 2.23 kB
build/preferences/index.min.js 1.35 kB
build/primitives/index.min.js 960 B
build/priority-queue/index.min.js 1.59 kB
build/react-i18n/index.min.js 702 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.75 kB
build/reusable-blocks/index.min.js 2.22 kB
build/reusable-blocks/style-rtl.css 281 B
build/reusable-blocks/style.css 281 B
build/rich-text/index.min.js 10.7 kB
build/server-side-render/index.min.js 1.77 kB
build/shortcode/index.min.js 1.52 kB
build/style-engine/index.min.js 1.51 kB
build/token-list/index.min.js 650 B
build/url/index.min.js 3.7 kB
build/vendors/inert-polyfill.min.js 2.48 kB
build/viewport/index.min.js 1.09 kB
build/warning/index.min.js 280 B
build/widgets/index.min.js 7.23 kB
build/widgets/style-rtl.css 1.21 kB
build/widgets/style.css 1.21 kB
build/wordcount/index.min.js 1.06 kB

compressed-size-action

@@ -47,8 +47,8 @@
"change-case": "^4.1.2"
},
"peerDependencies": {
"react": "^17.0.0",
"react-dom": "^17.0.0"
"react": "^18.0.0",
Copy link
Member

Choose a reason for hiding this comment

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

In order for the rest of the ecosystem to update smoothly and at their own pace, should we support both 17 and 18 as peer deps in most packages? (As long as our code is still compatible with 17, that is)

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure if our code will be compatible, that's the problem.

For example, I suspect that we'll need to update the useSelect hook to use useSyncExternalStore from React 18, otherwise it will not work 100% reliably with v18. Then the @wordpress/data library has a non-negotiable dependency on React 18, and that transitively affects all other libraries...

Let's keep the v17 compat requirement in mind, and see what we can do. Libraries like react-redux use a compat shim for useSyncExternalStore, and that allows them to support older versions back to React 16.

@jsnajdr
Copy link
Member Author

jsnajdr commented Nov 2, 2022

By far the biggest issue with the React 18 migration are unit tests firing warnings from react-test-renderer (and in turn from @testing-library/react):

An update to SomeComponent inside a test was not wrapped in act(...)

These warnings were quite common in React 17, too, but now React 18 seems to be much more sensitive about them, probably because of the concurrent mode, and tests often fail.

This act() issue is a major mess because it's quite hard to understand deeply what act() does, what kind of component behavior triggers the warnings and what's the correct way to avoid them.

In most affected libraries, someone filed a GitHub issue and most of the time the issue is closed after some time because most participants are confused and nobody is able to pinpoint the exact cause:

The @floating-ui/react-dom library recommends a certain workaround in its docs which kind of works, but it's a hack and is not entirely correct.

Tests are failing on act() when there is some async (i.e., executed in a Promise.then handler) update scheduled by the tested React UI.

Most typical case is fetching some data with @wordpress/data. This is Gutenberg code and we usually handle that by mocking the @wordpress/data calls, intercepting the promise that does the fetch and awaiting it inside act():

const fetchPromise = new Promise( ( resolve ) => {
  apiFetch.mockImplementation( async ( { path } ) => {
    resolve();
    return response;
  } );
} );

await act( () => fetchPromise );

This works but it requires access to the library internals (or mocking the internals). And it's not reliable: it relies on the fact that the act call finishes in the same or later event loop tick as the React update triggered by the finished fetch. Just one extra setTimeout( 0 ) will break it.

There are libraries where the async update is invisible: the useFloating hook from @floating-ui/react-dom will do something like:

function useFloating() {
  const [ data, setData ] = useState( { x: null, y: null } );
  useEffect( () => {
    computeDomPosition().then( ( data ) => setData( data ) );
  }, [] );
  return data;
}

I.e., it will calculate the DOM position of the rendered position and updates state in a .then handler. A component that uses useFloating will first render with default position ({ x: null, y: null }) and then, after a tick, will rerender with updated position.

But then a synchronous test that renders this component will miss the update:

render( <FloatingComponent title="floating title" /> );
expect( screen.getByTitle( 'floating title' ) ).toBeInTheDocument();

It will work (probably) because the assertion doesn't depend on positioning, but the state update will run a bit later, possibly during another test, and will trigger the "not wrapped in act()" warning.

A common solution (recommended even by the library docs) is to wait for the extra tick:

render( <FloatingComponent title="floating title" /> );
await act( async () => {} );
expect( screen.getByTitle( 'floating title' ) ).toBeInTheDocument();

But this is next to impossible to do reliably: every time the tested UI does call useFloating that changes position, I'm supposed to write a precisely placed await act()? I was able to do this for several tests in this PR, but only by stepping through the test suites in a debugger and tracking down places that trigger these updates.

Another library that performs the useEffect + Promise combo is react-navigation, a navigation/routing library for React Native, whose NavigationContainer component does this to get the initial state of the route. Some of our React Native unit tests do the same spurious await, like this one:

https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/image/test/edit.native.js#L85-L89

The Right Solution
The right solution, consistent with the Testing Library principles, is to realize that every async state update, be it a fetch, floating positioning or navigation init, should have some effect on the rendered UI. Placeholder disappears, element has an updated position, <NavigationContainer> renders its children instead of a placeholder.

And our tests need to wait for that update to happen. For example, for useFloating we'll probably need to write a Jest helper that does something like:

await waitFor( () => hasFinalPosition( screen.getByRole( 'popover' ) ) );

where hasFinalPosition will inspect the relevant DOM element style and check the positioning.

@jsnajdr
Copy link
Member Author

jsnajdr commented Nov 7, 2022

For example, for useFloating we'll probably need to write a Jest helper that does something like:

I just implemented this in #45587 and it really works 🎉

@tyxla
Copy link
Member

tyxla commented Nov 12, 2022

There's a failing test for the MediaReplaceFlow component in this branch.

I've created #45736 to address it separately.

@@ -3,6 +3,7 @@
*/
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { act } from 'react-test-renderer';
Copy link
Member

Choose a reason for hiding this comment

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

@jsnajdr perhaps we could use the re-exported act from @testing-library/react?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh yes, this was VSCode eagerly adding a random import statement as soon as I typed "act" 🙂

@@ -245,7 +244,8 @@ describe( 'Basic rendering', () => {
name: 'Edit',
} );

await user.click( editButton );
fireEvent.click( editButton );
Copy link
Member

Choose a reason for hiding this comment

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

I'm curious about those instances where we actually go back and refactor from user-library to fireEvent. Could you elaborate on the rationale for that?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure, but I think it was something like this: user.click is an async loop like:

for ( const action of pointerActions ) {
  await wait() // promisified setTimeout( 0 )
  act( () => pointerAction( action ) );
}

I.e. there is an async loop and the act() calls are synchronous. So, the update from computePosition().then() falls in between the pointerAction calls and is not wrapped in act().

But it's possible it's all bogus and user.click is fine. We'll need to revisit this. It's been a few weeks since I originally did these particular changes and today I know much more about how async act() works.

@jsnajdr
Copy link
Member Author

jsnajdr commented Dec 1, 2022

Technically, we're still using the non-concurrent mode and the old React 17 APIs

Only the unit test suites are in full React 18 concurrent mode. In that sense, the tests are one step ahead 🙂 There is still some flakiness there and some remaining "not wrapped in act()" warnings. After ironing them out, we'll try to enable concurrent mode for the production editor.

@youknowriad
Copy link
Contributor

There's a subtle change that was missed here:

In we remove this code

function gutenberg_register_vendor_scripts( $scripts ) {
$extension = SCRIPT_DEBUG ? '.js' : '.min.js';
gutenberg_override_script(
$scripts,
'react',
gutenberg_url( 'build/vendors/react' . $extension ),
// See https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#externalising-react.
SCRIPT_DEBUG ? array( 'wp-react-refresh-entry', 'wp-polyfill' ) : array( 'wp-polyfill' )
);
gutenberg_override_script(
$scripts,
'react-dom',
gutenberg_url( 'build/vendors/react-dom' . $extension ),
array( 'react' )
);
}
add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' );
The react version that is on Core will be used instead. The problem is that code is in the wordpress-6.0 folder (previous version we did a react upgrade) and this folder is going to be removed very soon because the minimum required version of WP in the Gutenberg plugin is going to be updated to 6.1 now.

In other words, we need to move that code to client-assets.php of the 6.2 folder or to lib/client-assets (if we think we'll be upgrading the version often).

That said, we shouldn't forget to update the version in core as well, when updating the packages, so I'm adding the "backport to php" label as a reminder.

@youknowriad youknowriad added the Backport to WP Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Dec 6, 2022
mpkelly pushed a commit to mpkelly/gutenberg that referenced this pull request Dec 7, 2022
* Upgrade React packages to v18

* Upgrade framer-motion to get React 18 support and updated types

* React Native: upgrade to 0.69.4

* React Native: upgrade libraries

* LinkControl: fix unit tests

* Components: fix unit tests

* Block Editor: fix unit tests

* NUX: fix unit tests

* useSelect: fix unit tests (partially)

* LinkSettings test: fix finding blocks by label text

* BlockDraggable test: fix finding blocks by label text

* React Native test helpers: fix getting blocks

* Block Library tests: fix finding blocks by label text

* ToggleGroupControl: fix unit test by waiting for tooltip

* File Block: update snapshots to account for empty children

* Embed native tests: improve mocked API response

* Embed native tests: wait for rich preview to appear

* Format Library: fix finding blocks by label text

* Edit Post: fix finding blocks by label text

* Update native snapshots

* useNestedSettingsUpdate: deoptimize/unbatch dispatching the updateBlockListSettings actions

* Color Palette: wait for dropdown to appear

* Add custom Jest matcher: toBePositionedPopover

* Use toBePositionedPopover matcher in tests

* Mobile - Update tests

* Mobile - Update gitignore

* Mobile - Update ruby config

* [Mobile] - React Native 0.69.4 Upgrade - Android (WordPress#43486)

* Mobile - React Native 0.69.4 upgrade, base Android changes

* Mobile - Remove RNGestureHandlerEnabledRootView since its now deprecated

* Mobile - Update bundle android script

* [Mobile] - React Native 0.69.4 Upgrade - iOS

* Mobile - Check for a local bundle running with metro and use a jsbundle as a fallback

* Remove duplicated import of Gesture handler

* Remove deprecated initialization for Reanimated

* Update Podfile.lock after updating dependencies

* Remove React peer deps from packages that don't need them

* Add changelog entries about React 18 upgrade

* Extract useIsScreenReaderEnabled hook, set state only if enabled=true

* Mobile - Update Podfile.lock

Co-authored-by: Marin Atanasov <tyxla@abv.bg>
Co-authored-by: Gerardo <gerardo.pacheco@automattic.com>
Co-authored-by: Derek Blank <derekpblank@gmail.com>
@danieliser
Copy link
Contributor

So is the current version of all these packages that require React 18 not ready for consumption? Using any of them requires using all of them from my testing due to peerDependencies, unless you want to use the ignore flag every time which we don't.

Further pushing to actually try and use them resulted in typescript issues everywhere from underlying usage of @types/react with versions less than 18.

'CheckboxControl' cannot be used as a JSX component.
  Its element type 'ReactElement<any, any> | Component<Props, any, any> | null' is not a valid JSX element.
    Type 'Component<Props, any, any>' is not assignable to type 'Element | ElementClass | null'.
      Type 'Component<Props, any, any>' is not assignable to type 'ElementClass'.
        The types returned by 'render()' are incompatible between these types.
          Type 'React.ReactNode' is not assignable to type 'import("/home/daniel/contentcontrol/content-control/node_modules/@types/react/index").ReactNode'.
            Type '{}' is not assignable to type 'ReactNode'.ts(2786)

@jsnajdr
Copy link
Member Author

jsnajdr commented Dec 22, 2022

Type 'React.ReactNode' is not assignable to type 'import("/home/.../node_modules/@types/react/index").ReactNode'

This error indicates that there are two versions of @types/react being imported, the old and new one. Can you find where the old version is coming from? From your project's package.json, from some 3rd party library, from one of the @types/wordpress__* DefinitelyTyped packages?

Using any of them requires using all of them

Unfortunately it was not feasible to keep compatibility with React 17. The @wordpress/components package, one of the fundamental ones, depends on 3rd party libraries that are already React 18 only, and that requirement would trickle down to all other packages. Discussed in this comment: #45235 (comment)

@danieliser
Copy link
Contributor

danieliser commented Dec 22, 2022

@jsnajdr I did track it down via package-lock.json to a few packages overall, I believe though that some of the @types/wordpress__* packages import @wordpress/element directly as part of its typings, due to this its currently locked on a version using React 17.

I know @types/wordpress__compose does this for sure, already started a patch, but haven't been able to test that it would actually work without further modifications.

DefinitelyTyped/DefinitelyTyped@master...danieliser:DefinitelyTyped:master

@danieliser
Copy link
Contributor

I believe it may be that outdated version of @wordpress/element being used in all the @types/wordpress__* packages that is causing the component type errors.

But this also mixes in with my other issue I created about the supposedly empty releases for all the packages that could in fact contain breaking changes that are not getting documented: #46730

@danieliser
Copy link
Contributor

danieliser commented Dec 23, 2022

Appears to be coming from @types/wordpress__components

image

Will test overrides locally to see if simply changing its deps to use the newer @wordpress/element@5 package fixes it.

@danieliser
Copy link
Contributor

Confirmed, simply changing that dependency in the @types/wordpress__components package fixed the bulk of the TS errors.

There are a few straggling errors that didn't exist before but there are only 6 and I'll figure those out shortly.

@danieliser
Copy link
Contributor

Ugg, just me or is that types package woefully untested.

Many of the type files in it import packages not in package.json.

Am I missing something, or should those all be listed?

Had to add the following to get it to pass npm test wordpress__components

"@types/wordpress__rich-text": "^3.4.6",
"@types/tinycolor2": "^1.4.3",
"@types/wordpress__notices": "3.5.0",

@danieliser
Copy link
Contributor

Also, what branch are the current releases in? trunk does not contain the "current" npm release for @wordpress/components @23.0.0.

Trunk shows those changes which are clearly live for the world as Unreleased

@danieliser
Copy link
Contributor

PR submitted that seemed to resolve it for me, no idea if/when it gets approved, though would love some extra testers: DefinitelyTyped/DefinitelyTyped#63716

@Mamaduka Mamaduka removed the Backport to WP Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Jan 26, 2023
@Mamaduka
Copy link
Member

I've removed backport label. The changes will be part of the general package update.

@gziolo
Copy link
Member

gziolo commented Feb 13, 2023

@desrosj discovered some issues with peer dependencies defined in some React libraries when testing WordPress core with Node 18.14.0 and npm: 9.3.1: WordPress/wordpress-develop#4028. I filed an issue #48009 in Gutenberg with steps to reproduce.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Mobile App - i.e. Android or iOS Native mobile impl of the block editor. (Note: used in scripts, ping mobile folks to change) Needs Dev Note Requires a developer note for a major WordPress release cycle
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants