TIL 22-04-04 (2)
React.js
Today I Learned ... react.js
🙋 My Dev Blog
에어비앤비 디자인 시스템 따라하기
스토리북(storybook)
- 비주얼 테스트: 컴포넌트들을 독립적으로 관리하고 변화를 살펴볼 수 있음.
- 스토리(story)란 ?
-> 컴포넌트의 다양한 출력 형태를 구성한 페이지
1. storybook 설치
> yarn add -dev @storybook/react
2. 스토리북 실행 명령어 - package.json 수정
"scripts" : {
"storybook" : "start-storybook -p 9001 -c .storybook",
}
3. 스토리 파일 생성
- /src/stories/InputStory
import React from "react";
import { storiesOf } from "@storybook/react";
import Input from "../component/Input";
storiesOf("Input", module).add("기본 설정", () => <Input />);
storiesOf 함수
- 스토리를 스토리북 도구에 추가해줌
- storiesOf()의 첫번째 인수 = 스토리북 도구에 표시할 스토리 이름
- 두번째 인수 = module
- add()의 첫번째 인수 = 스토리북 도구에 표시할 메뉴 이름
- 두번째 인수 = 콜백 (Input 컴포넌트 반환)
4. .storybook
폴더 (root) 생성 후 연결
- /.storybook/config.js
import { configure } from "@storybook/react";
function loadStories() {
require('../src/stories/InputStory');
}
configure(loadStories, module);
5. npm run storybook
> npm run storybook
- Input 태그가 포함된 스토리북 도구가 나타남. (브라우저에서 열림)
- 주소는 http://localhost:9001/?path=/story/input--기본-설정
스토리북 활용법
- 스토리에 여러 형태의 컴포넌트를 추가하고, 새 스토리를 자동으로 스토리북에 연결.
- ./src/stories/InputStory.jsx
import React from 'react';
import { storiesOf } from '@storybook/react';
import Input from '../component/Input';
storiesOf('Input', module)
.add('기본 설정', () => <Input name="name" />)
.add('label 예제', () => <Input name="name" label="이름" />);
- 이처럼 스토리에 여러 형태의 Input 컴포넌트를 추가해서 비주얼 테스트를 할 수 있다.
- 컴포넌트에 다양한 기능이나 디자인 추가시 스토리북을 사용하면 된다!
스토리 추가하기
- 카운터 스토리 추가
( 지난 예제에서 제작했던 NewCounter.jsx를 이용 )
- ./src/component/Newcounter.jsx (복습)
import React from 'react';
class NewCounter extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.increaseCount = this.increaseCount.bind(this);
}
static getDerivedStateFromProps(props, state) {
const { count } = props;
return {
count,
newCount: count === state.count ? state.newCount : count,
};
}
increaseCount() {
this.setState(({ newCount }) => ({
newCount: newCount + 1,
}));
}
render() {
return (
<div>
현재 카운트 : {this.state.newCount}
<button onClick={this.increaseCount}>카운트 증가</button>
</div>
);
}
}
export default NewCounter;
-> getDerivedStateFromProps()를 이용하여, 외부에서 값이 변경될 시 그것도 반영한다.
❕ 자세한 내용은 dev blog의 이전 글을 참고.
- ./src/stories/NewCounterStory.jsx
import React from "react";
import { storiesOf } from "@storybook/react";
import NewCounter from "../component/NewCounter";
storiesOf("NewCounter", module).add("기본 설정", () => (
<NewCounter count={0} />
));
- 스토리북에 스토리 추가하기
/.storybook/config.js
import { configure } from "@storybook/react";
function loadStories() {
require('../src/stories/InputStory');
require('../src/stories/NewCounterStory'); // 👈 require로 추가
}
configure(loadStories, module);
저장하는 순간, 자동으로 웹팩이 빌드되면서 스토리북 도구가 리로드된다.
스토리가 자동으로 스토리북에 추가되도록 설정
- 매번 story가 추가될 때 마다 config.js를 수정하는 것은 비효율적임.
- /.storybook/config.js
import { configure } from "@storybook/react";
import interopRequireDefault from 'babel-runtime/helpers/interopRequireDefault';
function loadStories() {
const context = require.context('../src/stories', true, /Story\.jsx$/); // 정규표현식 - Story.jsx로 끝나는 파일
context.keys().forEach((srcFile) => {
interopRequireDefault(context(srcFile));
});
}
configure(loadStories, module);
- require.context()함수로 src/stories 폴더의 스토리 목록을 가져옴. (정규표현식으로 찾기)
- context()함수는 require()과 동일한 기능을 하며, 가변 경로를 사용할때 쓸 수 있음.
📌 require.context
require.context는 기준 디렉토리로부터 정규표현식에 해당하는 모든 모듈을 불러올 수 있는 웹팩 컴파일러의 특별한 기능이다.
require.context를 사용하면 컴파일타임에 매칭되는 모든 모듈을 웹팩 빌드 디펜던시에 추가하게 되고 덕분에 매칭되는 모든 모듈을 런타임에 불러올 수 있다.
- interopRequireDefault(context(srcFile))은 context() 함수로 임포트한 파일 중 default 항목을 임포트함.
+) 참고 - > npm install -D babel-runtime
로 설치 후 진행함.
스토리북 확장 (addons)
- 이벤트 작동 테스트 -
addon-actions
- 컴포넌트 사용 (jsx)코드 출력 -
addon-jsx
addon-actions
패키지 설치
> npm install -D @storybook/addons @storybook/addon-actions
- addon-actions 설정 추가
- /.storybook/addons.js
import '@storybook/addon-actions/register';
- InputStory에 addon-actions 적용
- /src/stories/InputStory.jsx
import React from "react";
import { storiesOf } from "@storybook/react";
import { action } from "@storybook/addon-actions";
import Input from "../component/Input";
storiesOf("Input", module)
.add("기본 설정", () => <Input name="name" />)
.add("label 예제", () => <Input name="name" label="이름" />)
.add("onChange 예제", () => (
<Input name="name" onChange={action("onChange 이벤트 발생")} /> // 👈 action() 사용
));
- onChange 이벤트가 발생할 때 마다 스토리북 도구 하단에 Actions 창에 뜨게 된다.
- action() 의 인수로는 좌측에 나올 이벤트 설명을 입력하면 된다.
addon-jsx
설치 + 설정 추가(register_
> npm i -D storybook-addon-jsx
- /.storybook/addons.js
import '@storybook/addon-actions/register';
import 'storybook-addon-jsx/register';
- config.js 수정
-
addon-jsx는 새로운 예제 추가 함수를 storyOf함수에 추가하므로, config.js를 수정해야 함.
-
/.storybook/config.js
import { configure, setAddon } from "@storybook/react";
import interopRequireDefault from 'babel-runtime/helpers/interopRequireDefault';
import JSXAddon from 'storybook-addon-jsx'; // 👈 추가된 부분 1
function loadStories() {
const context = require.context('../src/stories', true, /Story\.jsx$/);
context.keys().forEach((srcFile) => {
interopRequireDefault(context(srcFile));
});
}
setAddon(JSXAddon); // 👈 추가된 부분 2
configure(loadStories, module);
- Story 파일 수정
- add() 함수가 아닌 addWithJSX() 함수를 사용해서 스토리에 컴포넌트 추가.
+)
🔨 에러 발생함
'jsx'라는 것을 못찾는다는 뜻 같은데, 구글링 해봐도 다 고쳐봐도 계속 해결이 안된다.
내가 storybook 설치할때 뭔가 버전 충돌이 일어난건지 root에 존재한다는 식으로 에러가 떠서
npm i -f (강제 설치)로 설치하긴 했는데 이때문인지는 잘 모르겠다 ...
Error Breaking 에서 추후에 다루도록 하겠다. 🤦♀️
Author And Source
이 문제에 관하여(TIL 22-04-04 (2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@thisisyjin/TIL-22-04-04-2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)