Storybook for React Native

repository·next·Indexed 23 days ago

https://github.com/storybookjs/react-native

An open source tool for developing React Native UI components in isolation without running the full application. It includes a universal `withStorybook` wrapper for Metro entry-point swapping and a suite of on-device addons including `@storybook/addon-ondevice-actions`, `@storybook/addon-ondevice-backgrounds`, and `@storybook/addon-ondevice-controls`.

Tokens
69K
Snippets
213
Records
307
Agent score
76%

What's inside Storybook for React Native

  1. Understand the Storybook configuration files

    next

    The Storybook configuration consists of several key files that work together:

    • main.ts: The primary configuration entry point for story discovery and addons.
    • preview.tsx: Configures the story rendering environment and global parameters.
    • index.tsx: The entry point for the Storybook UI and runtime behavior.
    • storybook.requires.ts: Automatically generated file containing story imports, addon registrations, preview configuration, and HMR setup. Do not edit this file manually.
  2. Detect the current Storybook version

    next

    Before starting an upgrade, identify the currently installed version using the following signals to avoid ambiguity:

    • Package Versions: Check package.json for @storybook/react-native, storybook, @storybook/react, and @storybook/addon-ondevice-*.
    • Config Directory: Check if the configuration folder is .storybook/ or .rnstorybook/.
    • Metro Configuration: Look for imports like metro/withStorybook, metro/withStorybookConfig, or the usage of withStorybook (default vs named).
    • Story Format: Determine if the project uses CSF (Component Story Format) or the older storiesOf API.
    • Generated Files: Check for the existence of storybook.requires.js or storybook.requires.ts.
  3. Use React Native Storybook on the web

    next

    If you are using React Native Web, you can run Storybook on the web in two ways:

    1. Run Native Storybook on the web: Use the native implementation directly.
    2. Setup a parallel Web Storybook: Set up a standard Web Storybook alongside your native one using the @storybook/react-native-web-vite framework. This provides access to the full Storybook feature set and easier web deployment, at the cost of additional configuration and setup.
  4. Auto-detection of controls from TypeScript types

    next

    If you do not explicitly define argTypes, Storybook can automatically infer controls from your component's TypeScript prop types:

    • string $\rightarrow$ text control
    • boolean $\rightarrow$ boolean control
    • 'sm' | 'md' | 'lg' (union of strings) $\rightarrow$ select control
    • number $\rightarrow$ number control
    interface ButtonProps {
      label: string; // → text control
      disabled: boolean; // → boolean control
      size: 'sm' | 'md' | 'lg'; // → select control
      count: number; // → number control
    }
    
    export default {
      component: Button,
      // No argTypes needed - controls auto-detected!
    };
  5. Use the State-First development approach

    next

    Instead of building a component and then adding states, try the State-First approach:

    1. Identify all possible states from the design (e.g., loading, error, success, empty).
    2. Create stories for each of these states in Storybook.
    3. Implement the component logic to satisfy all existing stories.
    4. Refine the component based on the visual feedback from the stories.
  6. Understand the differences between React Native Storybook and Web Storybook

    next

    Storybook for React Native is designed for maximum code reuse from the web by using the same Component Story Format (CSF) and core Storybook internal APIs. However, the runtime and rendering models differ significantly:

    • Runtime Environment: Runs in a native mobile environment (and basic web support) instead of a browser.
    • Preview Model: Runs directly inside your app with limited isolation, whereas Web Storybook runs in an iframe.
    • Addons: Supports core addons (like controls and actions), but does not support the full web addon ecosystem.
    • Development Server: Uses the Metro bundler (or others) instead of Webpack or Vite.
    • Rendering: It is integrated as a React Native component within your app, rather than being a separate standalone application.
    • Deployment: You deploy it by shipping to TestFlight or other mobile app distribution platforms, rather than hosting it on the web.
  7. Select the correct Storybook setup flow

    next

    Determine which setup guide to follow based on your project structure:

    • Re.Pack: Project has rspack.config or webpack.config and uses @callstack/repack.
    • Expo Router: Project has an app/ directory with _layout.tsx and uses expo-router.
    • Expo: Project uses Expo but does not use file-based routing (expo-router).
    • React Native CLI: Project uses @react-native-community/cli with no Expo.
  8. Wrap stories with decorators

    next

    Decorators are functions used to wrap your stories in arbitrary markup (like Providers, Themes, or Layout wrappers). This is useful when your components expect specific context or styling environments.

    Decorators can be applied at the global, component, or story level. In React Native, a decorator is a function that receives the Story component and returns a React element.

    Note: When using a functional component as a decorator, you must render the story using <Story /> or call it as a function Story() to enable rendering.

    import type { Meta, StoryObj } from '@storybook/react-native';
    import { View } from 'react-native';
    import { Button } from './Button';
    
    const meta: Meta<typeof Button> = {
      component: Button,
      decorators: [
        (Story) => (
          <View style={{ padding: 16 }}>
            <Story />
          </View>
        ),
      ],
    };
    
    export default meta;
  9. Use EXPO_PUBLIC_STORYBOOK_ENABLED to toggle Storybook

    next

    The environment variable EXPO_PUBLIC_STORYBOOK_ENABLED is used to control the visibility of Storybook in both the Metro bundler and the application entrypoint.

    1. In Metro: Setting it to 'true' enables Storybook module resolution via withStorybook.
    2. In App Code: Use it to conditionally render the Storybook UI component (imported from ./.rnstorybook) instead of your main application component.