You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Share react/jsx-runtime from the manager so addons can use libraries built with the automatic JSX runtime
#37127
Is your feature request related to a problem? Please describe.
The manager runs its own React (18.3.1 in Storybook 10.6.5) and shares it with addons through globalsNameReferenceMap: react, react-dom and react-dom/client. It does not share react/jsx-runtime or react/jsx-dev-runtime.
So when an addon's manager entry renders a React component library compiled with the automatic JSX runtime, that library's import { jsx } from 'react/jsx-runtime' isn't externalized. The bundler resolves it to whatever React the project has installed. In a React 19 project, React 19's jsx-runtime then runs against the manager's React 18 and throws:
TypeError: Cannot read properties of undefined (reading 'recentlyCreatedOwnerStacks')
React 19's jsx-runtime reads React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, which React 18 doesn't have. In a React 18 project it doesn't crash, but the addon still ships a second copy of the runtime.
The automatic runtime is what React recommends and the default in most toolchains (TypeScript "jsx": "react-jsx", @vitejs/plugin-react, Babel preset-react with runtime: "automatic"). The React 19 upgrade guide says the new JSX transform "is now required", and React logs an "outdated JSX transform" warning otherwise. So a library built the recommended way breaks once an addon renders it in the manager.
How to see it:
In a Storybook 10 React project with react@19, add a manager entry that registers a panel.
In the panel, render a component from a library whose dist contains import { jsx } from "react/jsx-runtime".
Open the panel. The manager throws the error above.
Rebuild the library with "jsx": "react" (classic runtime). The panel renders.
Describe the solution you'd like
Add react/jsx-runtime and react/jsx-dev-runtime to the manager globals, mapped to the manager React's own runtime (for example __REACT_JSX_RUNTIME__ and __REACT_JSX_DEV_RUNTIME__), and include them in globalPackages so addon builds externalize them, as they already do for react.
React 18.3.1 ships both entry points, and compiled jsx() / jsxs() / Fragment calls are the same across React 17–19. So a library compiled against React 19 would run on the manager's React 18.
Describe alternatives you've considered
Compile every library an addon uses with the classic runtime ("jsx": "react", as addon-kit does). This is what we do today. It pushes library authors onto the transform React calls outdated, only so Storybook addons can use their components, and an addon author can't change a third-party library's build.
Alias react/jsx-runtime in the addon's build to a small React.createElement shim. It works, but every addon has to rediscover and maintain it.
Are you able to assist to bring the feature to reality?
no
Additional context
Found while adding @just-web/react-image-compare to the panel of storybook-addon-vis. For now that library ships with the classic runtime. We'd switch it back once the manager shares react/jsx-runtime.
Related: #31513 (a guidance request that names the same jsx-runtime rewrite problem), #19722.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Is your feature request related to a problem? Please describe.
The manager runs its own React (18.3.1 in Storybook 10.6.5) and shares it with addons through
globalsNameReferenceMap:react,react-domandreact-dom/client. It does not sharereact/jsx-runtimeorreact/jsx-dev-runtime.So when an addon's manager entry renders a React component library compiled with the automatic JSX runtime, that library's
import { jsx } from 'react/jsx-runtime'isn't externalized. The bundler resolves it to whatever React the project has installed. In a React 19 project, React 19'sjsx-runtimethen runs against the manager's React 18 and throws:React 19's
jsx-runtimereadsReact.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, which React 18 doesn't have. In a React 18 project it doesn't crash, but the addon still ships a second copy of the runtime.The automatic runtime is what React recommends and the default in most toolchains (TypeScript
"jsx": "react-jsx",@vitejs/plugin-react, Babelpreset-reactwithruntime: "automatic"). The React 19 upgrade guide says the new JSX transform "is now required", and React logs an "outdated JSX transform" warning otherwise. So a library built the recommended way breaks once an addon renders it in the manager.How to see it:
react@19, add a manager entry that registers a panel.distcontainsimport { jsx } from "react/jsx-runtime"."jsx": "react"(classic runtime). The panel renders.Describe the solution you'd like
Add
react/jsx-runtimeandreact/jsx-dev-runtimeto the manager globals, mapped to the manager React's own runtime (for example__REACT_JSX_RUNTIME__and__REACT_JSX_DEV_RUNTIME__), and include them inglobalPackagesso addon builds externalize them, as they already do forreact.React 18.3.1 ships both entry points, and compiled
jsx()/jsxs()/Fragmentcalls are the same across React 17–19. So a library compiled against React 19 would run on the manager's React 18.Describe alternatives you've considered
"jsx": "react", asaddon-kitdoes). This is what we do today. It pushes library authors onto the transform React calls outdated, only so Storybook addons can use their components, and an addon author can't change a third-party library's build.react/jsx-runtimein the addon's build to a smallReact.createElementshim. It works, but every addon has to rediscover and maintain it.__REACT__directly from library code. Fragile, not type-safe, and it still leaves thejsx-runtimeimports to rewrite (as Need guidance on avoiding triple-bundling React #31513 notes).Are you able to assist to bring the feature to reality?
no
Additional context
Found while adding
@just-web/react-image-compareto the panel ofstorybook-addon-vis. For now that library ships with the classic runtime. We'd switch it back once the manager sharesreact/jsx-runtime.Related: #31513 (a guidance request that names the same
jsx-runtimerewrite problem), #19722.Storybook 10.6.5, React 19.3.1 (project) / 18.3.1 (manager), Node 26.7.0.
All reactions