
@storybook/react-native 라이브러리를 이용해서 앱에서 Storybook 구현
(문서대로 할 경우, 정상적으로 구현 됩니다)
@storybook/react & @storybook/addon-react-native-web 라이브러리를 이용해서 웹사이트에서 Storybook 구현
(해당 방법은 제대로 된 구현법을 찾을 수 없으며, 여러 문서들을 짜집기해서 구현을 시도했지만 작동하지 않는다. 예전 버전인 v5 자료만 보일뿐이며 작동이 가능한지조차 의문)
→ 위 같은 이유로 해당 문서에서는 1번 방법을 설명하겠습니다.
npx sb init --type react_native
// "npx sb init --type react_native" 이후에 생성되는 "storybook-generate" scripts
// storybook.requires.js 파일을 생성해준다
yarn storybook-generate

App.tsx
...
// 해당 코드를 주석처리하고
// export default App;
// 해당 코드를 넣어준다
export { default } from './.storybook';
metro.config.js
module.exports = {
/* existing config */
resolver: {
resolverMainFields: ['sbmodern', 'react-native', 'browser', 'main'],
},
};
main.js
module.exports = {
stories: ['./stories/**/*.stories.?(ts|tsx|js|jsx)'],
addons: [
'@storybook/addon-ondevice-controls',
'@storybook/addon-ondevice-actions',
'@storybook/addon-essentials',
'@storybook/addon-styling',
],
};
storybook.requires.js
/* do not change this file, it is auto generated by storybook. */
import {
configure,
addDecorator,
addParameters,
addArgsEnhancer,
clearDecorators,
} from '@storybook/react-native';
import { argsEnhancers } from '@storybook/addon-actions/dist/modern/preset/addArgs';
import { decorators, parameters } from './preview';
import '@storybook/addon-ondevice-controls/register';
import '@storybook/addon-ondevice-actions/register';
global.STORIES = [
{
titlePrefix: '',
directory: './.storybook/stories',
files: '**/*.stories.?(ts|tsx|js|jsx)',
importPathMatcher:
'^\\.[\\\\/](?:\\.storybook\\/stories(?:\\/(?!\\.)(?:(?:(?!(?:^|\\/)\\.).)*?)\\/|\\/|$)(?!\\.)(?=.)[^/]*?\\.stories\\.(?:ts|tsx|js|jsx)?)$',
},
];
if (decorators) {
if (__DEV__) {
// stops the warning from showing on every HMR
require('react-native').LogBox.ignoreLogs([
'`clearDecorators` is deprecated and will be removed in Storybook 7.0',
]);
}
// workaround for global decorators getting infinitely applied on HMR, see https://github.com/storybookjs/react-native/issues/185
clearDecorators();
decorators.forEach((decorator) => addDecorator(decorator));
}
if (parameters) {
addParameters(parameters);
}
try {
argsEnhancers.forEach((enhancer) => addArgsEnhancer(enhancer));
} catch {}
const getStories = () => {
return {
'./.storybook/stories/Button.stories.js': require('./stories/Button.stories.js'),
};
};
configure(getStories, module, false);
예시에 사용될 컴포넌트 기본 구성 (SomeComponent.tsx)
// SomeComponent
interface DefaultProps {
text: string;
isDisabled: boolean;
onPress: () => void;
};
const SomeComponent = ({ text, isDisabled, onPress }: DefaultProps) => {
return (
...
)
}
기본 사용법
import SomeComponent from 'components/SomeComponent';
...
export default {
title: '카테고리 제목',
component: SomeComponent,
args: {
text: 'text',
isDisabled: false,
onPress: () => {},
},
decorators: [
(Story) => (
<View>
<Story />
</View>
),
],
};
export const Default = {
args: {},
};
하위탭 생성 (Disabled)
...
export default {
title: '카테고리 제목',
component: SomeComponent,
args: {
text: 'text',
isDisabled: false,
onPress: () => {},
},
decorators: [
(Story) => (
<View>
<Story />
</View>
),
],
};
export const Default = {
args: {},
};
export const Disabled = {
args: {
isDisabled: true;
}
};
1개의 탭에 여러 컴포넌트 생성
...
export default {
title: '카테고리 제목',
component: (args) => {
return (
<>
<Text>기본</Text>
<SomeComponent {...args} />
<Text>비활성화</Text>
<SomeComponent {...args} isDisabled={true} />
</>
)
},
args: {
text: 'text',
isDisabled: false,
onPress: () => {},
},
decorators: [
(Story) => (
<View>
<Story />
</View>
),
],
};
export const Default = {
args: {},
};
styled-components와 함께 사용법
import { ThemeProvider } from 'styled-components/native';
import theme from 'styles/theme';
export default {
...
decorators: [
(Story) => (
<ThemeProvider theme={theme}>
<View>
<Story />
</View>
</ThemeProvider>
),
],
};
...
storybook.requires.js 에서 작성한 스토리 파일을 자동으로 생성해주는 유용한 라이브러리이지만 현재 v6.5 버전 기준으로 파일을 불러오는 양식이 맞지않아 사용할 수 없다.React환경에서 Storybook구현법과 생태계는 잘 갖춰져 있지만,
React Native에서 Storybook의 구현은 공식문서에서도 언급했듯이 React와 비교해서 부수적인 기능과 편의성이 떨어진다는 것을 절실히 느꼈다.