분류 Reactjs

React 용 스토리북 튜토리얼 - 간단한 구성 요소 만들기

컨텐츠 정보

  • 조회 306 (작성일 )

본문

격리 된 간단한 구성 요소 빌드 


CDD (Component-Driven Development) 방법론에 따라 UI를 구축 할 것입니다. 구성 요소에서 시작하여 화면으로 끝나는 '하향식'에서 UI를 구축하는 프로세스입니다. CDD는 UI를 구축 할 때 직면하게 되는 복잡성의 정도를 확장하는 데 도움이 됩니다.


https://www.learnstorybook.com/intro-to-storybook/react/en/simple-component/ 


Task 


Task component in three states 


태스크는 우리 앱의 핵심 구성 요소입니다. 각 작업은 정확히 어떤 상태에 있는지에 따라 약간 다르게 표시됩니다. 확인 된 (또는 선택되지 않은) 확인란, 작업에 대한 일부 정보 및 "핀"버튼을 표시하여 작업을 목록에서 위아래로 이동할 수 있습니다. 이것을 합치면 다음 소품이 필요합니다.


  • title – 작업을 설명하는 문자열
  • state-현재 작업이 어떤 목록에 있고 체크 해제되어 있습니까?


Task 빌드를 시작할 때 먼저 위에서 스케치 한 다양한 유형의 작업에 해당하는 테스트 상태를 작성합니다. 그런 다음 Storybook을 사용하여 모의 데이터를 사용하여 격리 된 구성 요소를 빌드 합니다. 각 상태에 따라 구성 요소의 모양을 수동으로 테스트 할 것입니다.


설정하기 


먼저 작업 구성 요소와 함께 제공되는 스토리 파일 인 src/components/Task.js 및 src/components/Task.stories.js를 만들어 보겠습니다.


작업의 기본 구현부터 시작하겠습니다. 필요한 속성과 작업에 대해 수행 할 수 있는 두 가지 작업 (목록간에 이동)을 취합니다.


// src/components/Task.js

import React from 'react';

export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) {
  return (
    <div className="list-item">
      <input type="text" value={title} readOnly={true} />
    </div>
  );
}

위에서 우리는 Todos 앱의 기존 HTML 구조를 기반으로 Task에 대한 간단한 마크 업을 렌더링합니다.


아래에서는 스토리 파일에 Task의 세 가지 테스트 상태를 구축합니다.

// src/components/Task.stories.js

import React from 'react';
import { action } from '@storybook/addon-actions';

import Task from './Task';

export default {
  component: Task,
  title: 'Task',
  // Our exports that end in "Data" are not stories.
  excludeStories: /.*Data$/,
};

export const taskData = {
  id: '1',
  title: 'Test Task',
  state: 'TASK_INBOX',
  updatedAt: new Date(2018, 0, 1, 9, 0),
};

export const actionsData = {
  onPinTask: action('onPinTask'),
  onArchiveTask: action('onArchiveTask'),
};

export const Default = () => <Task task={{ ...taskData }} {...actionsData} />;

export const Pinned = () => <Task task={{ ...taskData, state: 'TASK_PINNED' }} {...actionsData} />;

export const Archived = () => (
  <Task task={{ ...taskData, state: 'TASK_ARCHIVED' }} {...actionsData} />
);

Storybook에는 구성 요소와 하위 스토리의 두 가지 기본 수준이 있습니다. 각 스토리를 구성 요소의 순열로 생각하십시오. 구성 요소 당 필요한 만큼 많은 스토리를 가질 수 있습니다.


Component 

  • Story
  • Story
  • Story

문서화 중인 구성 요소에 대해 Storybook에 알리기 위해 다음을 포함하는 기본 내보내기를 만듭니다.

  • component -- 구성 요소 자체,
  • title -- Storybook 앱의 사이드 바에 있는 구성 요소를 참조하는 방법,
  • excludeStories -- Storybook에서 스토리로 렌더링 하면 안되는 스토리 파일로 내보내기.

스토리를 정의하기 위해 각 테스트 상태에 대한 함수를 내보내 스토리를 생성합니다. 스토리는 주어진 상태에서 렌더링 된 요소 (즉, 소품 세트가 있는 구성 요소)를 반환하는 함수입니다. 마치 Stateless Functional Component와 같습니다.


action()을 사용하면 클릭시 스토리 북 UI의 작업 패널에 나타나는 콜백을 만들 수 있습니다. 따라서 핀 버튼을 만들 때 버튼 클릭이 성공했는지 테스트 UI에서 확인할 수 있습니다.


구성 요소의 모든 순열에 동일한 작업 집합을 전달해야 하므로 이를 단일 actionsData 변수로 묶고 React의 {... actionsData} props 확장을 사용하여 한 번에 모두 전달하는 것이 편리합니다. <Task {... actionsData}>는 <Task onPinTask = {actionsData.onPinTask} onArchiveTask = {actionsData.onArchiveTask}>와 동일합니다.


actionsData로 액션을 묶는 또 다른 좋은 점은 나중에 살펴 보겠지만 해당 변수를 내보내고 이 컴포넌트를 재사용 하는 컴포넌트에 대한 스토리에서 액션을 사용할 수 있다는 것입니다.


스토리를 만들 때 기본 작업 (taskData)을 사용하여 구성 요소가 예상하는 작업의 모양을 구축합니다. 이것은 일반적으로 실제 데이터가 어떻게 보이는지에서 모델링 됩니다. 다시 말하지만,이 모양을 내 보내면 나중에 보게 될 스토리에서 다시 사용할 수 있습니다.


작업은 UI 구성 요소를 격리하여 빌드 할 때 상호 작용을 확인하는 데 도움이 됩니다. 종종 앱 컨텍스트에서 가지고 있는 기능과 상태에 액세스 할 수 없습니다. action()을 사용하여 스텁에 넣습니다.


Config 


Storybook 구성을 몇 가지 변경하여 최근에 만든 스토리뿐 아니라 이전 장에서 변경된 CSS 파일을 사용할 수 있도록 해야 합니다.


Storybook 구성 파일 (.storybook / main.js)을 다음으로 변경하여 시작합니다.


// .storybook/main.js

module.exports = {
  stories: ['../src/components/**/*.stories.js'],
  addons: [
    '@storybook/preset-create-react-app',
    '@storybook/addon-actions',
    '@storybook/addon-links',
  ],
};

위의 변경을 완료 한 후 .storybook 폴더 안에 다음과 같이 preview.js라는 새 파일을 추가합니다.


// .storybook/preview.js

import '../src/index.css';

이 작업을 마치면 Storybook 서버를 다시 시작하면 세 가지 작업 상태에 대한 테스트 사례가 생성됩니다.


https://www.learnstorybook.com/intro-to-storybook//inprogress-task-states.mp4


상태 구축 


이제 스토리 북 설정, 스타일 가져 오기 및 테스트 케이스가 구축되었으므로 디자인에 맞게 구성 요소의 HTML을 구현하는 작업을 빠르게 시작할 수 있습니다.


구성 요소는 현재 여전히 기본입니다. 먼저 너무 자세히 설명하지 않고 디자인을 달성하는 코드를 작성합니다.


// src/components/Task.js

import React from 'react';

export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) {
  return (
    <div className={`list-item ${state}`}>
      <label className="checkbox">
        <input
          type="checkbox"
          defaultChecked={state === 'TASK_ARCHIVED'}
          disabled={true}
          name="checked"
        />
        <span className="checkbox-custom" onClick={() => onArchiveTask(id)} />
      </label>
      <div className="title">
        <input type="text" value={title} readOnly={true} placeholder="Input title" />
      </div>

      <div className="actions" onClick={event => event.stopPropagation()}>
        {state !== 'TASK_ARCHIVED' && (
          // eslint-disable-next-line jsx-a11y/anchor-is-valid
          <a onClick={() => onPinTask(id)}>
            <span className={`icon-star`} />
          </a>
        )}
      </div>
    </div>
  );
}

앞서 가져온 CSS와 결합 된 위의 추가 마크 업은 다음 UI를 생성합니다.


https://www.learnstorybook.com/intro-to-storybook/finished-task-states.mp4


데이터 요구 사항 지정 


React에서 propTypes를 사용하여 구성 요소가 예상하는 데이터의 모양을 지정하는 것이 가장 좋습니다. 자체 문서 화일 뿐만 아니라 문제를 조기에 발견하는 데 도움이 됩니다.


// src/components/Task.js

import React from 'react';
import PropTypes from 'prop-types';

export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) {
  // ...
}

Task.propTypes = {
  task: PropTypes.shape({
    id: PropTypes.string.isRequired,
    title: PropTypes.string.isRequired,
    state: PropTypes.string.isRequired,
  }),
  onArchiveTask: PropTypes.func,
  onPinTask: PropTypes.func,
};

이제 작업 구성 요소가 잘못 사용되면 개발 중 경고가 표시됩니다.


동일한 목적을 달성하는 또 다른 방법은 TypeScript와 같은 JavaScript 유형 시스템을 사용하여 구성 요소 속성에 대한 유형을 만드는 것입니다.


Component built! 


이제 서버가 필요하지 않거나 전체 프런트 엔드 애플리케이션을 실행하지 않고도 구성 요소를 성공적으로 구축했습니다. 다음 단계는 나머지 작업 상자 구성 요소를 유사한 방식으로 하나씩 구축하는 것입니다.


보시다시피, 구성 요소를 분리하여 구축하는 것은 쉽고 빠릅니다. 가능한 모든 상태를 조사하고 테스트 할 수 있기 때문에 버그가 적고 다듬어 진 고품질 UI를 생성 할 수 있습니다.


Automated Testing 


Storybook은 구축 중에 애플리케이션 UI를 수동으로 테스트 할 수 있는 좋은 방법을 제공했습니다. '스토리'는 앱을 계속 개발하면서 Task의 모양이 깨지지 않도록 하는 데 도움이 됩니다. 그러나이 단계에서는 완전히 수동 프로세스이며 누군가가 각 테스트 상태를 클릭하여 오류나 경고 없이 제대로 렌더링 되는지 확인해야 합니다. 자동으로 할 수 없나요?


Snapshot testing 


스냅 샷 테스트는 주어진 입력에 대해 구성 요소의 "알려진 양호한"출력을 기록한 다음 나중에 출력이 변경 될 때마다 구성 요소에 플래그를 지정하는 방법을 말합니다. 이는 구성 요소의 새 버전을 보고 변경 사항을 확인할 수 있는 빠른 방법이기 때문에 Storybook을 보완합니다.


구성 요소가 변경되지 않는 데이터를 렌더링 하여 매번 스냅 샷 테스트가 실패하지 않도록 합니다. 날짜 또는 무작위로 생성 된 값과 같은 항목을주의하십시오.


Storyshots 애드온을 사용하면 각 스토리에 대한 스냅 샷 테스트가 생성됩니다. 다음 개발 종속성을 추가하여 사용하십시오.


yarn add -D @storybook/addon-storyshots react-test-renderer

그런 다음 다음 내용이 포함 된 src/storybook.test.js 파일을 만듭니다.


// src/storybook.test.js

import initStoryshots from '@storybook/addon-storyshots';
initStoryshots();

이것이 바로 실 테스트를 실행하고 다음 출력을 볼 수 있습니다.



Task test runner 

이제 각 태스크 스토리에 대한 스냅 샷 테스트가 있습니다. Task 구현을 변경하면 변경 사항을 확인하라는 메시지가 표시됩니다.