Search code examples
androidiosreact-nativeexpostorybook

Why does my React Native app not switch between storybook and the app?


I followed https://storybook.js.org/tutorials/intro-to-storybook/react-native/en/get-started/ in order to switch between storybook and the app when running certain CLI commands.

Firstly, I have an app.config.js file that looks like this:

module.exports = {
  name: 'mobile-app',
  slug: 'mobile-app',
  version: '1.0.0',
  extra: {
    storybookEnabled: process.env.STORYBOOK_ENABLED,
  },
  orientation: 'portrait',
  icon: './assets/icon.png',
  userInterfaceStyle: 'light',
  splash: {
    image: './assets/splash.png',
    resizeMode: 'contain',
    backgroundColor: '#ffffff',
  },
  assetBundlePatterns: ['**/*'],
  ios: {
    supportsTablet: true,
  },
  android: {
    adaptiveIcon: {
      foregroundImage: './assets/adaptive-icon.png',
      backgroundColor: '#ffffff',
    },
  },
  web: {
    favicon: './assets/favicon.png',
  },
};

Afterwards, I updated my App.tsx file with logic to switch between storybook and the app if the STORY_ENABLED flag is set to true:

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, View } from 'react-native';
import Constants from 'expo-constants';
import { ThemeProvider } from '@rneui/themed';
import theme from './styles/theme';
import { Text } from './components/Text/Text';

function App() {
  const styles = StyleSheet.create({
    container: {
      alignItems: 'center',
      backgroundColor: theme.lightColors?.gold120,
      flex: 1,
      justifyContent: 'center',
    },
  });

  return (
    <ThemeProvider theme={theme}>
      <View style={styles.container}>
        <Text h3>Whereas recognition of the inherent dignity</Text>
        <StatusBar style="auto" />
      </View>
    </ThemeProvider>
  );
}
let AppEntryPoint = App;

// Render Storybook if storybookEnabled is true
if (Constants.expoConfig?.extra?.storybookEnabled === 'true') {
  /* eslint-disable-next-line @typescript-eslint/no-var-requires */
  AppEntryPoint = require('./.storybook').default;
}

export default AppEntryPoint;

Note that I had to add the optional chaining and just an eslint disable for typescript.

Thirdly, I added the following script to my package.json:

 "scripts": {
// ...scripts,
    "storybook": "sb-rn-get-stories STORYBOOK_ENABLED='true' && expo start"
  },

The big difference from the documentation is removing the && before STORYBOOK_ENABLED='true' because I'm on a windows machine, according to react native storybook problem with process.env.STORYBOOK_ENABLED

The idea is that I can use yarn start to start the app proper and use yarn storybook to set the flag to true and start storybook.

However, yarn storybook always opens the app instead. Am I missing something here?


Solution

  • The tutorial template got updated recently to add a fix for windows.

    You can redownload the template or update the scripts manually to use cross-env.

    "storybook": "sb-rn-get-stories && cross-env STORYBOOK_ENABLED='true' expo start",
    "storybook:ios": "sb-rn-get-stories && cross-env STORYBOOK_ENABLED='true' expo start --ios",
    "storybook:android": "sb-rn-get-stories && cross-env STORYBOOK_ENABLED='true' expo start --android"
    

    also make sure to add cross-env as a dev dependency

    yarn add -D cross-env
    

    That should solve your issue.