storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.09k stars 9.25k forks source link

Cannot find module 'react-dom/client' in render.jss under React 18 #18402

Open dontsave opened 2 years ago

dontsave commented 2 years ago

Describe the bug render.jss is erroring after upgrading to React 18 when attempting to access react-dom/client

To Reproduce Run storybook with React 18.1.0

System

System:
    OS: macOS 10.15.7
    CPU: (8) x64 Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
  Binaries:
    Node: 16.14.2 - ~/.nvm/versions/node/v16.14.2/bin/node
    Yarn: 1.22.10 - ~/frame.io/web-app/node_modules/.bin/yarn
    npm: 8.5.0 - ~/.nvm/versions/node/v16.14.2/bin/npm
  Browsers:
    Chrome: 102.0.5005.61
    Firefox: 100.0.2
    Safari: 15.1
  npmPackages:
    @storybook/addon-actions: 6.3.7 => 6.3.7 
    @storybook/addon-knobs: 6.3.0 => 6.3.0 
GuyGooL5 commented 2 years ago

I'm facing the same problem after upgrading to 6.5.6. I'm using storybook for react 17 with builder-vite. Node version: v14.17.5 NPM version: 8.3.0

dependencies:

    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    ...

devDependencies :

    "@storybook/addon-actions": "^6.5.6",
    "@storybook/addon-essentials": "^6.5.6",
    "@storybook/addon-links": "^6.5.6",
    "@storybook/api": "^6.5.6",
    "@storybook/builder-vite": "^0.1.36",
    "@storybook/react": "^6.5.6"
    "vite": "^2.7.2",
    ...
grimor commented 2 years ago

@dontsave I have same issue but with React v17. On React v18 it works fine. Maybe it incorrectly resolve dependencies and it try to load React v17 on Storybook (which doesn't export react-dom/client, which cause that issue.)

@GuyGooL5 About your issue. I found out that line https://github.com/storybookjs/storybook/blob/next/app/react/src/client/preview/render.tsx#L76 cause trouble. It previously looked like that https://github.com/storybookjs/storybook/blob/c0b53a529601d0bed83cecc01a2bf493089cc26d/app/react/src/client/preview/render.tsx#L77

When I've changed that line to previous version, it started working, but I'm using Webpack 4 instead of Vite, but maybe root cause is the same.

GuyGooL5 commented 2 years ago

@grimor actually what solved it for me was changing "react-dom/client" to "react-dom"

grimor commented 2 years ago

@GuyGooL5 Cool, I've also found out that my webpack config overrides was overwriting IgnorePlugin used in storybook which tells webpack to ignore react-dom/client. When I've included that into my webpack config it build correctly without patching render.js file.

nichita-pasecinic commented 2 years ago

Facing the same issue after upgrade image

The project is on "react-dom": "^17.0.2", so why would it even look for react-dom/client ?

"@storybook/addon-actions": "^6.5.9",
"@storybook/addon-essentials": "^6.5.9",
"@storybook/addon-interactions": "^6.5.9",
"@storybook/addon-links": "^6.5.9",
"@storybook/addon-viewport": "^6.5.9",
"@storybook/addons": "^6.5.9",
"@storybook/builder-vite": "^0.1.38",
"@storybook/react": "^6.5.9",
"@storybook/testing-library": "^0.0.13",
"@storybook/theming": "^6.5.9",
"react": "^17.0.2",
"react-dom": "^17.0.2",
thibaudcolas commented 2 years ago

I’m facing the same issue as well in Storybook v6.5, with React 16, and no particular Webpack overrides that seem relevant to this.

This seems like a clear-cut bug to me – the Storybook rendering logic attempts to conditionally load react-dom/client, but at build time there’s no way for Webpack to tell that the import is conditional. So it’ll still attempt to resolve this no matter what:

https://github.com/storybookjs/storybook/blob/e2673f765722cbb542ef1b5cf8d533c8e746a127/app/react/src/client/preview/render.tsx#L76


I’ll try to further change my Webpack config in case I’m misunderstanding the relevance of my overrides (adding one rule and two plugins on top of the base config), and share a minimal repro case.

thibaudcolas commented 2 years ago

I’ve managed to reproduce the issue, and opened it separately at #18662 because it seems different to what everyone else is reporting here. I think my issue affects React 16 and 17 but clearly shouldn’t be a problem for React 18 users.

beeequeue commented 2 years ago

Can confirm this happening to us using React 17 and Storybook 6.5

Quick workaround that works for me is to mark react-dom/client as external in Storybook's Webpack config

// main.js
module.exports = {
  webpackFinal: (config) => {
    // Storybook 6.5 added support for React 18's new Root API, but fails to realize we
    // arent using React 18 yet, so it fails when it can't find it.
    // https://github.com/storybookjs/storybook/issues/18402
    config.externals = ["react-dom/client"]
  }
}
SpookyJelly commented 1 year ago

having same issue. Using sb for react 17 with vite.

// package.json
  "dependencies": {
    "react": "^17.0.0",
    "react-dom": "^17.0.0"
  },

"devDependencies":{
    "@storybook/react": "^6.5.15",

}

I can fix this erase all plugin with problems on storybook's main.ts. but It doesn't seem a total solution. Really no clue why react-dom/client appears in this context. Hope somebody solved this already

vgoreev commented 3 months ago

Just in case someone encountering the same issue with the latest Storybook packages combined with React 17.

We've got React 17 in our project but @storybook requires React 18 for its manager plugin. So I came up with this workaround. So essentially Storybook uses a package called @storybook/react-dom-shim to create a unified way of mounting and unmounting components. We need to explicitly tell storybook's webpack to use react-16 version of a shim. Here is a code that worked for me.

// main.ts
     ...

    webpackFinal(config) {
        config.resolve = {
            extensions: ['.ts', '.tsx', '.js', '.jsx'],
            alias: {
                react: getAbsolutePath('react'),
                'react-dom': getAbsolutePath('react-dom'),
                '@storybook/react-dom-shim': '@storybook/react-dom-shim/dist/react-16',
            },
        };

        return config;
    },