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

v1.0.0-beta.4 is incompatible with React <18 #147

Open
rossta opened this issue Sep 15, 2022 · 3 comments
Open

v1.0.0-beta.4 is incompatible with React <18 #147

rossta opened this issue Sep 15, 2022 · 3 comments

Comments

@rossta
Copy link

rossta commented Sep 15, 2022

Expected Behavior

From the README:

This package tries to support both the legacy React DOM interface (ReactDOM.render) and the new one introduced in React 18 (ReactDOM.createRoot).

The installed React version is tested at runtime by trying to import react-dom/client. If the import succeeds then the new API is used, otherwise we fallback to the legacy API.

I'd expect this library to work with React 17.

Actual Behavior

During webpack compilation, I see the following error:

ERROR in ./node_modules/react-components-rails/dist/index.js 1:1677-1703
Module not found: Error: Can't resolve 'react-dom/client' in '/Users/rosskaffenberger/dev/stitchfix/fe-infra-webpack-rails/gem/spec/sample/node_modules/react-components-rails/dist'

Dependencies:

  • react-component-rails 1.0.0-beta.4
  • react 17.0.2
  • react-dom 17.0.2

Analysis

It appears that the import from "react-dom/client" statement will not work in versions of React prior to 18.

One solution I can think of is for react-component-rails to be refactored in a way such that the behavioral differences between React 18+ and React <18 can be isolated and injected via separate imports from the consumer, i.e., something like the following:

  • apps using React 18: import ReactComponentRails from "react-component-rails"
  • apps using React <18: import ReactComponentRails from "react-component-rails/legacy"
@renchap
Copy link
Owner

renchap commented Sep 15, 2022

Thanks for your report.

This is weird as there is no import … from "react-dom/client" but a dynamic import (await import('react-dom/client')) which should be resolved at runtime and a failure means it fallbacks to the legacy import. But I guess webpack needs to resolve this path when generating the output before it sends it to the server?

I wanted to find a way to not require users to change their imports to use the legacy React DOM API. It looks like we could use ReactDOM.createRoot as it is exported from react-dom, but the react-dom/client export has a slightly different implementation and I do not know if it is safe to use the non-client export…

@rossta
Copy link
Author

rossta commented Sep 17, 2022

Yes, I misspoke about the import. It is the dynamic import that webpack can't process at compile time even though the module isn't requested until runtime.

I know react-component-rails is meant to be bundler-agnostic and, while I don't know for sure if behavior affects other bundlers, I do have a webpack-specific workaround. I can instruct webpack to load another module instead in place of react-dom/client using alias. The aliased module simply raises an error which react-component-rails gracefully handles in the dynamic import, falling back to React 17 rendering.

// ... add to existing webpack config
{
 // ...
  resolve: {
    alias: {
      'react-dom/client$': path.resolve('path/to/module/that/raises/error'),
    },
  },
};

@rossta
Copy link
Author

rossta commented Sep 17, 2022

Version detection could be another option. Something like:

  private loadReactDOMClient() {
    return new Promise<void>((resolve) => {
+      const [reactMajorVersion] = React.version && React.version.split('.') || '0';
+      if (parseInt(reactMajorVersion, 10) < 18) {
+        this.#ReactDOMClient = false
+        resolve()
+      }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants