github storybookjs/react-native v10.0.0-rc.1

pre-releaseone day ago

We're now preparing for the release of v10 and in this RC we have most if not all of the changes ready

Version 10 brings Storybook React Native in sync with Storybook core v10 and introduces improved Metro configuration.

Update your metro config

The withStorybook metro wrapper has been significantly simplified in v10. The key changes are:

  1. Import path unified - In v9, withStorybookConfig (from metro/withStorybookConfig) was a preview of the simplified API. In v10, this is now the standard behavior when importing withStorybook from metro/withStorybook
  2. onDisabledRemoveStorybook is removed - When enabled: false, Storybook is automatically removed from the bundle (no separate flag needed)
  3. Simpler defaults - Works out of the box with sensible defaults

Before (v9):

When using withStorybook with the old API:

const withStorybook = require('@storybook/react-native/metro/withStorybook');

module.exports = withStorybook(defaultConfig, {
  enabled: process.env.STORYBOOK_ENABLED === 'true',
  onDisabledRemoveStorybook: true, // This option no longer exists in v10
});

After (v10):

const { withStorybook } = require('@storybook/react-native/metro/withStorybook');

// Basic usage - works out of the box with defaults
module.exports = withStorybook(defaultConfig);

// Or with options
module.exports = withStorybook(defaultConfig, {
  // When false, automatically removes Storybook from bundle
  enabled: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true',
});

The updated config will automatically stub out the rnstorybook config folder when enabled is set to false as well as the storybook packages.
This makes it so that you don't need to wrap your imports of storybook with conditionals to avoid crashing the app.

for example:

// App.tsx
let AppEntryPoint = App;

if (process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true') {
  // Conditional import to avoid bundling Storybook in production
  AppEntryPoint = require('./.rnstorybook').default;
}

export default AppEntryPoint;

could now just be imported in a more natural way like this:

import StorybookUI from './.rnstorybook';

const isStorybook = process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === 'true';

export default function App() {
  return isStorybook ? <StorybookUI /> : <AppComponent />;
}

Don't miss a new react-native release

NewReleases is sending notifications on new releases.