Repository navigation
Support React 19 - #5955
Open
Eugene (OEvgeny) wants to merge 18 commits into
Open
Support React 19#5955Eugene (OEvgeny) wants to merge 18 commits into
Eugene (OEvgeny) wants to merge 18 commits into
Conversation
added 6 commits
October 21, 2026 19:32
…eparate React root React 19 removed ReactDOM.render() and unmountComponentAtNode(). The copy button is now rendered by createPortal() in the React tree of Web Chat, by the innermost scope (focus trap of the activity, or the composer) containing the element, so keyboard and focus events still reach the activity.
React 16 to 18 and Preact keep ReactDOM.render(). On React 19, the ESM build imports react-dom/client through the import map; other builds throw a clear error.
The IIFE build evaluated its bundled React DOM 16 even when window.ReactDOM was set, which fails with React 19 in window.React. The ESM tests are skipped until react-film no longer imports render() from react-dom (spyip/react-film#110).
Resolve the conflict in CustomElementsComposer.tsx by keeping both changes: - #5951: the module-level `registerCustomElement()` with its `WeakMap` from class to tag name, so each class is defined once with its own tag and Strict Mode can call `useMemo()` twice. - This branch: the per-composer `CustomElementPortalRegistry`, passed to `useReactCodeBlockCopyButtonClass()`, put in the context and rendered by the root `<CustomElementPortalScope />`. The copy button class is created per registry, so each composer still gets its own class and tag; the registry discarded by Strict Mode's second `useMemo()` call never defines a class.
Collaborator
Author
|
We need to support backward compatibility down to React 16 |
Eugene (OEvgeny)
marked this pull request as ready for review
October 22, 2026 06:47
Eugene (OEvgeny)
requested review from
William Wong (compulim),
Chris Whitten (cwhitten) and
Thomas Durnford (tdurnford)
as code owners
October 22, 2026 06:47
Eugene (OEvgeny)
marked this pull request as draft
October 22, 2026 07:14
Eugene (OEvgeny)
marked this pull request as ready for review
October 22, 2026 07:36
Replaces the portal approach: the copy button is an HTMLElement subclass that builds a native <button> with the same classes, ARIA and test ID, so it needs no React root (React 19 removed render()) and its events bubble through the DOM to the activity, e.g. ESCAPE. Removes CustomElementPortalRegistry, CustomElementPortalScope, the FocusTrap scope and wrapAsCustomElement; CodeBlock passes the localized strings as attributes again, as on main. Links spyip/react-film#110 in full in the skipped React 19 ESM tests.
- `createRootRequiredError()` is thrown explicitly: synchronously in the npm build on React 19, where "react-dom/client" cannot be imported. - Comments name the build of each branch: IIFE with the bundled React DOM 16.8.6, `window.ReactDOM` 19, static (ESM) build, npm build. - Static build: errors after `renderWebChat()` returned are logged with `console.error()` instead of an unhandled rejection.
"react-dom" exports createRoot() only through "react-dom/client"; a react-dom object with createRoot() could only come from a hand-merged window.ReactDOM in the IIFE build, which was untested and undocumented.
Collaborator
Author
|
Draft until we figure the react-film approach |
Eugene (OEvgeny)
added a commit
that referenced
this pull request
Oct 28, 2026
#5971) * Split renderWebChat()'s render schema into legacyReactDOMSchema and reactRootSchema * Use the React DOM of the page in the IIFE build of the Fluent theme The IIFE build bundled React DOM 16.8.6 (through renderWebChat() of botframework-webchat) and evaluated it on load against window.React, which crashes with React 19. Like "react", "react-dom" now resolves to window.ReactDOM; the bundled copy was only used by renderWebChat(), which the IIFE build does not export. * Add a React 19 test for the IIFE build of the Fluent theme * Remove react-dom/client from the baseline import map in HOSTING.md static/react-dom.baseline/client.js is never built (React 16 has no react-dom/client), and renderWebChat() does not import react-dom/client: on React 19, the host passes a root from createRoot(). * Test that renderWebChat() throws an error from root.render() synchronously * Add a React 19 test for the copy button of code blocks with the IIFE build Ported from #5955: the page creates its own root with createRoot() and renders <ReactWebChat> with React 19. * Name ReactDOM.createRoot() in the error of renderWebChat() for an invalid container * Say what keeps the ESM renderWebChat() test on emulated React 19: react-film imports render() by name * Expect the version of ReactDOM in the React 19 tests * Spy on root.render() with jest-mock in the React 18 renderWebChat() test * Add the changelog fragment --------- Co-authored-by: Eugene Olonov <eugeneolonov@microsoft.com>
added 6 commits
October 30, 2026 10:20
- renderWebChat.esm.html: use React 19 instead of React 18 without ReactDOM.render(), the static build loads on React 19 since #5980. - strictMode.esm.html: send a message, flip a carousel and click a suggested action on React 19 development in Strict Mode, without any console.error.
… keeps the typed inputs The card is rendered in useMemo(). In Strict Mode, React 19 calls it twice and keeps the first result, while the card reads its inputs from the DOM of the second render: Action.Submit sent empty values. The result is now reused when the inputs did not change.
React 19 ignores propTypes, and TypeScript types check the props. None of these components is exported, and no published file imports prop-types. Props that propTypes typed before are now readonly, as react/prefer-read-only-props asks.
added 3 commits
October 30, 2026 14:18
- useRef() needs an argument with @types/react@19.
- Composer of the component package renders children as nodes: its props no longer take the render function of the API Composer, which only type-checked on @types/react@16, where ReactNode includes {}.
- Composer of the full bundle calls a children function with extraStyleSet, as its typings say, instead of passing the function to Composer, which cannot render it.
CI type-checked only with @types/react@16, the baseline. The new step installs @types/react@19 in every workspace, since packages that declare @types/react@16 would otherwise keep their own copy. The tsd tests now create the elements instead of calling ReactDOM.render(), which @types/react-dom@19 no longer has.
Eugene (OEvgeny)
marked this pull request as ready for review
October 31, 2026 00:41
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changelog Entry
Added
@types/react@19, in PR #5955, by @OEvgenyRemoved
propTypesand theprop-typesdependency, React 19 ignores them, in PR #5955, by @OEvgenyFixed
Composerof the full bundle not calling achildrenfunction withextraStyleSet, in PR #5955, by @OEvgenyDescription
React 19 ran since #5961, #5963 and #5980, but it was not declared, tested in development or Strict Mode, or type-checked. This declares it, tests it, fixes what the tests found, and removes the remaining
propTypes.Design
propTypeswere on internal components, none is exported.Specific Changes
docs/HOSTING.md: React 16.8.6 to 19 supportedAdaptiveCardRenderer.tsx: one render per inputs;react19/strictMode.adaptiveCard.submit.html(React 18:strictMode/adaptiveCard.submit.html): posted value keptreact19/strictMode.esm.html: React 19 dev, Strict Mode: send (snapshot 1), carousel (2), suggested action (3), card submit (4)react19/renderWebChat.esm.html: real React 19Components.Composer:childrentyped as nodes, it never called a function;FullComposercalls achildrenfunction withextraStyleSetType definitions test: also with
@types/react@19Removed 37
propTypes,prop-typesfrom 4 packagesI have added tests and executed them locally
I have added
.changelog/<PR#>-<slug>.mdI have updated documentation
Review Checklist
z-index)package.jsonandpackage-lock.jsonreviewed