React Native – All about Storybook

Setup

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

npx storybook@latest init
  • Set unstable_allowRequireContext: true in “metro.config.js” file
...
const path = require('path');
const { generate } = require('@storybook/react-native/scripts/generate');

generate({
  configPath: path.resolve(__dirname, './.storybook'),
});

...
const config = {
    transformer: {
      unstable_allowRequireContext: true,
    },
    ...
};
  • Change root component
  • If you are developing micro frontend, you need to install “yarn add @react-native-async-storage/async-storage” in your Android/ iOS projects

Add a storybook component

  • Add a component
    storybook/stories/Text/index.tsx
    storybook/stories/Text/index.stories.tsx
  • Add component into storybook/stories/index.js
    import ‘./Text/index.stories’;

Load stories files inside different folders

How to wrap global storybook with a View?

// .storybook/preview.tsx
import React from 'react';
import { Provider } from 'react-native-paper';
...

const preview: Preview = {
  ...,
  decorators: [
    (Story) => (
      <Provider>
        <Story />
      </Provider>
    ),
  ],
};

...

Switch app to run story book

  • Install package
yarn add babel-plugin-transform-inline-environment-variables --d
  • Edit .babelrc
module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    [
      'transform-inline-environment-variables',
      {
        include: ['SHOW_STORYBOOK'],
      },
    ],
  ],
};
  • If there is error, edit .babelrc like this
{
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    [
      'transform-inline-environment-variables',
      {
        include: ['SHOW_STORYBOOK'],
      },
    ],
  ],
};
  • Add script into package.json
"restart-story": "rnstl; watchman watch-del-all; SHOW_STORYBOOK=1 react-native start --reset-cache",
"restart": "yarn install; watchman watch-del-all; yarn start --reset-cache"
  • Change App component to switch to storybook component
const App = () => {
  if (process.env.SHOW_STORYBOOK) {
    return <StorybookUIRoot />;
  } else {
    return <MainApp>;
  }
};
  • Run story book
yarn restart-story
  • Run normal app
    In order to run normal app you need to clear storybook cache
yarn restart

How to load Storybook on web?

When you can’t see storybook loaded on Web, do as below

  • Run iOS/ Android emulator
  • Make sure Storybook web URL (http://localhost:7007/ for example) can be opened in emulator browser
    • If it does, Web Storybook will be loaded
    • If it doesn’t, Web Storybook will not be loaded
  • For iOS simulator, Web’s “locahost” URL should work in Safari browser
  • For Android emulator, Web’s “locahost” URL doesn’t work
    • You need to change Web URL to “http://10.0.2.2:7007
    • Open “storybook/index.js”
    • Open “package.json”
"scripts": {
    ...
    "storybook": "start-storybook -h 10.0.2.2 -p 7007",
    ...
}

How to load stories file inside component folders? (old)

  • Install react-native-storybook-loader
    yarn add react-native-storybook-loader -D
  • Run this script to run react-native-storybook-loader
{
  "scripts": {
    "prestorybook": "rnstl"
  }
}
  • Fix this file storybook/index.js
...

import { loadStories } from './storyLoader';

...

// import stories
configure(() => {
  loadStories();
}, module);
  • Add this into package.json to define search directories
  "config": {
    "react-native-storybook-loader": {
      "searchDir": [
        "./src",
        "./storybook"
      ],
      "pattern": "**/*.stories.tsx",
      "outputFile": "./storybook/storyLoader.js"
    }
  }

How to simulate props change, action change?

Install knobs

import React from 'react';
import { storiesOf } from '@storybook/react-native';
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';
import YourComponent from './index';

const title = 'Hello Title';

function DummyParent() {
  return (
<>
        <YourComponent
          title={text('title', title, 'GROUP-ID1')}
          checked={boolean('checked', true, 'GROUP-ID1')}
          onPress={action('onPress')}
        />
        <YourComponent
          title={text('title', title, 'GROUP-ID2')}
          checked={boolean('checked', false, 'GROUP-ID2')}
          onPress={action('onPress')}
        />
</>
  );
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

storiesOf('Components', module)
  .addDecorator(withKnobs)
  .add('YourComponent', () => <DummyParent />);

Reference

maintaining-storybook-ft-yann-braga-rru-159

Be the first to comment

Leave a Reply

Your email address will not be published.


*