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

[Bug]: @storybook/nextjs React versions are inconsistent between Next.js and Storybook. #30646

Open
geonu-moloco opened this issue Feb 24, 2025 · 1 comment

Comments

@geonu-moloco
Copy link

geonu-moloco commented Feb 24, 2025

Describe the bug

When I try to use Storybook in Next.js project with @storybook/nextjs, the React version which is for used rendering components in Storybook is different from Next.js.

Next.js uses their bundled React when the project is configured to use "app router", and they also let us use our own React in node_modules when the porject is configured to use "pages router".
So if I installed React 18.3.1 and Next.js 15, and also If I configured the project to use "pages router", then the React version that is used for rendering should be 18.3.1

ref: /~https://github.com/vercel/next.js/blob/48f2588b0fea2bffb5bf6534169ee112438786a6/packages/next/next-runtime.webpack-config.js#L240-L247

But in @storybook/nextjs, it always force to use Next bundled React regardless of router configuration.
For Next.js 15.1.7, the version of bundled React is 19.0.0-rc-65e06cb7-20241218
This difference causes an inconsistency between Next.js rendered components and Storybook rendered components.

In my case, React 19 starts to provide ref within React props and it caused unexpected overwriting of ref pro.

ref:

if (tryResolve('next/dist/compiled/react')) {
addScopedAlias(baseConfig, 'react', 'next/dist/compiled/react');
}
if (tryResolve('next/dist/compiled/react-dom/cjs/react-dom-test-utils.production.js')) {
addScopedAlias(
baseConfig,
'react-dom/test-utils',
'next/dist/compiled/react-dom/cjs/react-dom-test-utils.production.js'
);
}
if (tryResolve('next/dist/compiled/react-dom')) {
addScopedAlias(baseConfig, 'react-dom$', 'next/dist/compiled/react-dom');
addScopedAlias(baseConfig, 'react-dom/client', 'next/dist/compiled/react-dom/client');
addScopedAlias(baseConfig, 'react-dom/server', 'next/dist/compiled/react-dom/server');
}

I think this aliasing behavior should be optional, and ideally it should follow the Next.js configuration (if the Next.js project is configured to use pages router, than make it not to configure those aliases)
Since Next.js with pages router doesn't require any features from React canary, it is safe to use React other than bundled version.

My current workaround is adding following config to Storybook's config, main.ts

const config: StorybookConfig = {
  ...
  webpackFinal: async (config) => {
    const unaliases = [
      'react',
      'react-dom/test-utils',
      'react-dom$',
      'react-dom/client',
      'react-dom/server',
    ];
    if (config.resolve?.alias) {
      for (const unalias of unaliases) {
        delete config.resolve?.alias[unalias];
      }
    }
    return config;
  },
  ...
};
export default config;

Reproduction link

https://stackblitz.com/edit/github-bmvmcb6b

Reproduction steps

  1. Go to above link
  2. Run yarn dev to run Next.js server.
  3. Visit http://localhost:3000
  4. See the text placed in the page. That's the React version which is used by Next.js. It should be 18.3.1
  5. Run yarn storybook to run Storybook.
  6. Visit http://localhost:6006
  7. See the text placed in the page. That's the React version which is used by Storybook Next.js integration. It should be 19.0.0-rc-65e06cb7-20241218

System

Storybook Environment Info:

  System:
    OS: macOS 15.3.1
    CPU: (12) arm64 Apple M3 Pro
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.12.0 - ~/.nvm/versions/node/v22.12.0/bin/node
    npm: 10.9.0 - ~/.nvm/versions/node/v22.12.0/bin/npm
    pnpm: 9.15.2 - ~/.nvm/versions/node/v22.12.0/bin/pnpm <----- active
  Browsers:
    Chrome: 133.0.6943.127
    Safari: 18.3

Additional context

Image Image
Copy link
Contributor

greptile-apps bot commented Feb 24, 2025

** Disclaimer** This information might be inaccurate, due to it being generated automatically
This can be fixed by modifying the webpack configuration in @storybook/nextjs. The relevant code is in code/frameworks/nextjs/src/config/webpack.ts. Add a check for the router type before applying React aliases: ts // In webpack.ts const useNextBundledReact = async (nextConfig) => { // Check if using pages router const usingPagesRouter = !nextConfig.experimental?.appDir; return !usingPagesRouter; }; export const webpack = async (config: Configuration, options: Options): Promise<Configuration> => { const shouldUseNextReact = await useNextBundledReact(options.nextConfig); if (shouldUseNextReact) { config.resolve.alias = { ...config.resolve.alias, 'react': path.dirname(require.resolve('next/package.json')), 'react-dom': path.dirname(require.resolve('next/package.json')), }; } return config; }; This will only apply the Next.js bundled React when not using the pages router.

About Greptile

This response provides a starting point for your research, not a precise solution.

Help us improve! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

Edit Issue Bot Settings · Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Needs Discussion
Development

No branches or pull requests

2 participants