React Native – All about Storybook

Setup

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npx storybook@latest init
npx storybook@latest init
npx storybook@latest init
  • Set unstable_allowRequireContext: true in “metro.config.js” file
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
...
const path = require('path');
const { generate } = require('@storybook/react-native/scripts/generate');
generate({
configPath: path.resolve(__dirname, './.storybook'),
});
...
const config = {
transformer: {
unstable_allowRequireContext: true,
},
...
};
... const path = require('path'); const { generate } = require('@storybook/react-native/scripts/generate'); generate({ configPath: path.resolve(__dirname, './.storybook'), }); ... const config = { transformer: { unstable_allowRequireContext: true, }, ... };
...
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?

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// .storybook/preview.tsx
import React from 'react';
import { Provider } from 'react-native-paper';
...
const preview: Preview = {
...,
decorators: [
(Story) => (
<Provider>
<Story />
</Provider>
),
],
};
...
// .storybook/preview.tsx import React from 'react'; import { Provider } from 'react-native-paper'; ... const preview: Preview = { ..., decorators: [ (Story) => ( <Provider> <Story /> </Provider> ), ], }; ...
// .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
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
yarn add babel-plugin-transform-inline-environment-variables --d
yarn add babel-plugin-transform-inline-environment-variables --d
yarn add babel-plugin-transform-inline-environment-variables --d
  • Edit .babelrc
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'transform-inline-environment-variables',
{
include: ['SHOW_STORYBOOK'],
},
],
],
};
module.exports = { presets: ['module:metro-react-native-babel-preset'], plugins: [ [ 'transform-inline-environment-variables', { include: ['SHOW_STORYBOOK'], }, ], ], };
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
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'transform-inline-environment-variables',
{
include: ['SHOW_STORYBOOK'],
},
],
],
};
{ presets: ['module:metro-react-native-babel-preset'], plugins: [ [ 'transform-inline-environment-variables', { include: ['SHOW_STORYBOOK'], }, ], ], };
{
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    [
      'transform-inline-environment-variables',
      {
        include: ['SHOW_STORYBOOK'],
      },
    ],
  ],
};
  • Add script into package.json
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"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"
"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"
"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
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const App = () => {
if (process.env.SHOW_STORYBOOK) {
return <StorybookUIRoot />;
} else {
return <MainApp>;
}
};
const App = () => { if (process.env.SHOW_STORYBOOK) { return <StorybookUIRoot />; } else { return <MainApp>; } };
const App = () => {
  if (process.env.SHOW_STORYBOOK) {
    return <StorybookUIRoot />;
  } else {
    return <MainApp>;
  }
};
  • Run story book
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
yarn restart-story
yarn restart-story
yarn restart-story
  • Run normal app
    In order to run normal app you need to clear storybook cache
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
yarn restart
yarn restart
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”
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"scripts": {
...
"storybook": "start-storybook -h 10.0.2.2 -p 7007",
...
}
"scripts": { ... "storybook": "start-storybook -h 10.0.2.2 -p 7007", ... }
"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
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"scripts": {
"prestorybook": "rnstl"
}
}
{ "scripts": { "prestorybook": "rnstl" } }
{
  "scripts": {
    "prestorybook": "rnstl"
  }
}
  • Fix this file storybook/index.js
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
...
import { loadStories } from './storyLoader';
...
// import stories
configure(() => {
loadStories();
}, module);
... import { loadStories } from './storyLoader'; ... // import stories configure(() => { loadStories(); }, module);
...

import { loadStories } from './storyLoader';

...

// import stories
configure(() => {
  loadStories();
}, module);
  • Add this into package.json to define search directories
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
"config": {
"react-native-storybook-loader": {
"searchDir": [
"./src",
"./storybook"
],
"pattern": "**/*.stories.tsx",
"outputFile": "./storybook/storyLoader.js"
}
}
"config": { "react-native-storybook-loader": { "searchDir": [ "./src", "./storybook" ], "pattern": "**/*.stories.tsx", "outputFile": "./storybook/storyLoader.js" } }
  "config": {
    "react-native-storybook-loader": {
      "searchDir": [
        "./src",
        "./storybook"
      ],
      "pattern": "**/*.stories.tsx",
      "outputFile": "./storybook/storyLoader.js"
    }
  }

How to simulate props change, action change?

Install knobs

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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 />);
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 />);
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.


*