Skip to content

Support React v19 in @module-federation/bridge-react #3537

Closed
@cascornelissen

Description

@cascornelissen

Clear and concise description of the problem

We're hoping to slowly migrate our MF-based codebase with about 20 projects in total from React 16 to React 19. We were planning on leveraging @module-federation/bridge-react to make it possible to run parts of our codebase with React 16 and other parts with React 19 in parallel. We've confirmed that what we're trying to do works with React 16 and React 18 but it looks like React 19 is not yet supported.

const isReact18 = ReactDOM.version.startsWith('18');
/**
* Creates a root for a container element compatible with both React 16 and 18
*/
export function createRoot(
container: Element | DocumentFragment,
options?: CreateRootOptions,
): Root {
if (isReact18) {
// For React 18, use the new createRoot API
// @ts-ignore - Types will be available in React 18
return (ReactDOM as any).createRoot(container, options);
}
// For React 16/17, simulate the new root API using render/unmountComponentAtNode
return {
render(children: React.ReactNode) {
// @ts-ignore - React 17's render method is deprecated but still functional
ReactDOM.render(children, container);
},
unmount() {
ReactDOM.unmountComponentAtNode(container);
},
};
}

Suggested solution

The required change is that createRoot has to be imported from react-dom/client instead of from react-dom directly since v19. Since adding something like the following line of code will break for everything lower than React v19 and dynamic imports don't make much sense for a library, we're a bit stumped on how we could implement this.

import ReactDOM from 'react-dom';
import ReactDOM19 from 'react-dom/client'; // This will break on react-dom 16, 17, and 18

Alternative

Somehow being able to pass our own createRoot function would shift the burden to the consumer. We haven't really investigated this approach so far but by making this possible it's up to the end-user to pass (possibly overwrite) the createRoot function. This way we could import it from the correct dependency depending on the context.

Additional context

The same probably applies to hydrateRoot but we're not using this in our project at the moment.

Validations

  • Read the Contributing Guidelines.
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions