Как создать приложение React с помощью Storybook

Перед дизайнерами пользовательского интерфейса и front-end разработчиками стоит задача создания чистых и последовательных пользовательских интерфейсов. В то же время тестирование является краеугольным камнем разработки программного обеспечения. Каждая часть программного проекта тестируется отдельно и изолируется от других элементов в модульных тестах. В контексте пользовательских интерфейсов эта практика была труднодостижима.

Теперь Storybook предоставляет фреймворк с открытым исходным кодом, который позволяет тестировать компоненты пользовательского интерфейса в изоляции от остальной части веб-сайта. Storybook представляет вам браузер всех компонентов вашего веб-приложения. Вы можете тестировать каждый компонент независимо и в различных конфигурациях. Инструмент работает как отдельное приложение вне вашего основного приложения, что означает, что вы можете тестировать свои компоненты, не беспокоясь о зависимостях или требованиях, специфичных для приложения.

В этом руководстве я покажу вам, как использовать Storybook для создания простого React-приложения. Приложение будет представлять собой приложение для перевода единиц измерения, и я буду использовать Storybook для демонстрации отдельных компонентов и самой страницы приложения. Я не предполагаю никаких предварительных знаний о React или Storybook. Я предполагаю, что вы знакомы с JavaScript и Node, и на вашем компьютере установлена актуальная версия менеджера пакетов npm.

Предварительные условия:

  • Node 14
  • Okta CLI

Создание компонентов React с помощью Storybook

В этом разделе я покажу вам, как создать React-приложение и реализовать компоненты, отображаемые в Storybook. Эти компоненты послужат основой для приложения по переводу единиц измерения. Для начала откройте терминал в выбранной вами папке и выполните следующую команду для создания нового приложения React.

npx create-react-app@5 react-storybook --use-npm
Войти в полноэкранный режим Выйти из полноэкранного режима

Команда create-react-app создает новую папку, react-storybook, и инициализирует базовый скелет приложения. Далее превратите это базовое приложение React в приложение Storybook. Перейдите в только что созданную папку и выполните следующую команду.

npx sb@6 init
Войти в полноэкранный режим Выйти из полноэкранного режима

Когда появится запрос, ответьте «да», чтобы установить пакет sb. Инициализация Storybook создаст новую папку stories внутри папки src и заполнит ее некоторыми предварительно созданными демонстрационными компонентами и историями, которые будут использоваться Storybook. Откройте папку проекта в вашей любимой IDE.

Вы можете сразу же протестировать Storybook. Откройте сеанс терминала в папке проекта и выполните следующую команду.

npm run storybook
Войти в полноэкранный режим Выйти из полноэкранного режима

Команда запускает приложение Storybook и открывает вкладку браузера (http://localhost:6006). Сейчас вы увидите только компоненты, которые Storybook устанавливает по умолчанию. Вы можете оставить Storybook запущенным, пока разрабатываете свое приложение.

Используя вашу IDE, создайте новый файл с именем src/stories/Components.jsx. Это будет модуль, который будет содержать некоторые основные компоненты пользовательского интерфейса. В рамках данного руководства я помещу все эти компоненты в один модуль. На практике, возможно, вы захотите распределить их по нескольким файлам. Откройте src/stories/Components.jsx и вставьте следующий код.

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import './Components.css';

export function Input({ size, type, label, name, placeholder, onChange }) {
  return (
    <label className={`input-component input-component--${size}`}>
      <span>{label}</span>
      <input
        type={type==='text' ? 'text' : 'number'}
        step={type==='floating-point' ? 'any' : undefined}
        name={name}
        placeholder={placeholder}
        onChange={onChange}
      />
    </label>
  );
};

Input.propTypes = {
  size: PropTypes.oneOf(['medium', 'large']),
  type: PropTypes.oneOf(['text', 'number', 'floating-point']),
  label: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  placeholder: PropTypes.string.isRequired,
  onChange: PropTypes.func,
};

Input.defaultProps = {
  size: 'medium',
  type: 'text',
  label: 'Enter a value',
  name: 'input',
  placeholder: 'Please enter a value',
  onChange: undefined
};

export function Select({ size, label, options, onChange }) {
  return (
    <label className={`select-component select-component--${size}`}>
      <span>{label}</span>
      <select className="select-component" onChange={onChange}>
        {options.map((option) => <option value={option.value}>{option.description}</option>)}
      </select>
    </label>
  );
};

Select.propTypes = {
  size: PropTypes.oneOf(['medium', 'large']),
  label: PropTypes.string.isRequired,
  options: PropTypes.arrayOf(PropTypes.shape({
    value: PropTypes.string.isRequired,
    description: PropTypes.string.isRequired
  })).isRequired,
  onChange: PropTypes.func,
};

Select.defaultProps = {
  size: 'medium',
  label: 'Options',
  options: []
};

export function Tabs({ children }) {
  const [active, setActive] = useState(0);

  const onTabClick = (newActive) => () => {
    setActive(() => newActive);
  };

  return (
    <div className="tabs-component">
      <div className="tabs-row">
        {children.map((child, index) => <div className={`tab ${index === active ? "active" : ""}`} onClick={onTabClick(index)}>{child.props.label}</div>)}
      </div>
      <div className="tabs-content">
        {children[active]}
      </div>
    </div>
  );
};

Tabs.propTypes = {
  children: PropTypes.instanceOf(Array).isRequired,
};

Tabs.defaultProps = {
  children: []
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Этот модуль экспортирует три компонента. Input — это настраиваемый элемент <input> с меткой для ввода текста или чисел, Select — это выпадающий элемент <select>, обернутый в метку, а Tabs — это компонент, который показывает свои дочерние элементы в отдельной вкладке. Я использую функцию React propTypes для указания свойств, которые каждый компонент React ожидает в качестве аргументов, что позволяет Storybook извлекать эту мета-информацию и отображать ее пользователю. Чтобы немного оформить компоненты, создайте файл src/stories/Components.css и заполните его следующим содержимым.

.input-component {
  display: flex;
  flex-direction: column;
  margin-bottom: 1rem;
}

.input-component span {
  display: block;
  margin-bottom: 0.5rem;
}

.input-component.input-component--large input {
  font-size: 1.2rem;
  padding: 0.5rem 1rem;
}

.select-component {
  display: flex;
  flex-direction: column;
  margin-bottom: 1rem;
}

.select-component span {
  display: block;
  margin-bottom: 0.5rem;
}

.select-component.select-component--large select {
  font-size: 1.2rem;
  padding: 0.5rem 1rem;
}

.tabs-component .tabs-row {
  font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  display: flex;
}

.tabs-component .tabs-row .tab {
  border: 1px solid #EEEEEE;
  border-bottom: none;
  border-top-right-radius: 4px;
  border-top-left-radius: 4px;
  padding: 0.5rem 1rem;
  cursor: pointer;
}

.tabs-component .tabs-row .tab.active {
  background-color: #EEEEEE;
  cursor: auto;
}

.tabs-component .tabs-content {
  border: 1px solid #EEEEEE;
  padding: 0.5rem 1rem;
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Таким образом, компоненты можно использовать как React-компоненты в вашем приложении. Но вы также хотите, чтобы их можно было просматривать через Storybook. Для этого вам нужно будет создать по одному файлу для каждого компонента. Начните с создания файла src/stories/Input.stories.jsx и введите в него следующий код.

import React from 'react';

import { Input } from './Components';

export default {
  title: 'Components/Input',
  component: Input,
};

const Template = (args) => <Input {...args} />;

export const Normal = Template.bind({});

Normal.args = {
  label: 'Normal Input',
  placeholder: 'Enter your value',
  size: 'normal'
};

export const Large = Template.bind({});

Large.args = {
  label: 'Large Input',
  placeholder: 'Enter your value',
  size: 'large'
};

export const Number = Template.bind({});

Number.args = {
  label: 'Integer Number',
  placeholder: 'Enter your value',
  size: 'large',
  type: 'number'
};

export const FloatingPoint = Template.bind({});

FloatingPoint.args = {
  label: 'Floating Point Number',
  placeholder: 'Enter your value',
  size: 'large',
  type: 'floating-point'
};
Вход в полноэкранный режим Выйти из полноэкранного режима

export default в верхней части файла сообщает Storybook, как называется компонент и на какой React-компонент ссылаются истории в этом файле. Последующие экспорты Normal, Large, Number и FloatingPoint представляют отдельные истории или случаи использования этого компонента. Каждая история определяет член args, который определяет свойства, передаваемые компоненту. Создавать истории таким образом быстро, поэтому сейчас создадим следующую историю для компонента Select. Создайте файл src/stories/Select.stories.jsx и вставьте в него следующее содержимое.

import React from 'react';

import { Select } from './Components';

export default {
  title: 'Components/Select',
  component: Select,
};

const Template = (args) => <Select {...args} />;

export const Default = Template.bind({});

Default.args = {
  size: 'medium',
  label: 'Select an Option',
  options: [
    { value: 'a', description: 'Option A' },
    { value: 'b', description: 'Option B' },
    { value: 'c', description: 'Option C' },
  ]
};

export const Large = Template.bind({});

Large.args = {
  size: 'large',
  label: 'Select an Option',
  options: [
    { value: 'a', description: 'Option A' },
    { value: 'b', description: 'Option B' },
    { value: 'c', description: 'Option C' },
  ]
};
Войти в полноэкранный режим Выйти из полноэкранного режима

Этот файл определяет две истории для компонента Select. Одна история показывает его в нормальном размере, а другая — в большом. Наконец, сделайте то же самое для компонента Tabs. Создайте файл src/stories/Tabs.stories.jsx и заполните его содержимым, приведенным ниже.

import React from 'react';

import { Tabs } from './Components';

export default {
  title: 'Components/Tabs',
  component: Tabs,
};

const Template = (args) => <Tabs {...args} />;

export const Default = Template.bind({});

Default.args = {
  children: [
    <div label="One">Content One</div>,
    <div label="Two">Content Two</div>,
    <div label="Three">Content Three</div>,
  ]
};
Вход в полноэкранный режим Выйдите из полноэкранного режима

Теперь вы готовы протестировать свои новые компоненты в Storybook. Если вы еще не сделали этого, откройте терминал в папке проекта и выполните следующую команду.

npm run storybook
Войти в полноэкранный режим Выйти из полноэкранного режима

Команда запускает приложение Storybook и открывает вкладку браузера (http://localhost:6006). Вы можете просматривать компоненты на левой боковой панели. Истории, которые вы только что создали, можно найти под заголовком Компоненты, и когда вы выберете, например, историю Input -> Number, вы увидите нечто подобное тому, что показано на рисунке ниже.

Компонент отображается в основном виде, а расположенные над ним значки позволяют изменить фон, размер экрана и даже проверить размеры макета компонента. Ниже основного вида вы можете вручную настроить параметры, передаваемые компоненту. Я приглашаю вас поиграть со всеми возможностями, которые предоставляет Storybook.

Создание приложения конвертера единиц измерения с использованием историй компонентов Storybook

Я буду использовать библиотеку convert-units для реализации приложения конвертации единиц измерения. Откройте второй терминал в папке вашего проекта и выполните приведенную ниже команду.

npm install -E convert-units@2.3.4
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь в вашей IDE создайте новый файл src/stories/Converter.jsx и заполните его содержимым, приведенным ниже.

import React, { useState } from 'react';
import PropTypes from 'prop-types';
import * as convert from 'convert-units';
import { Input, Select } from './Components';

export const Converter = ({measure}) => {
  const possibilities = convert().possibilities(measure).map((unit) => {
      const descr = convert().describe(unit);
      return {
          value: descr.abbr,
          description: `${descr.singular} (${descr.abbr})`
      };
  });

  const [fromUnit, setFromUnit] = useState(possibilities[0].value);
  const [toUnit, setToUnit] = useState(possibilities[0].value);
  const [fromValue, setFromValue] = useState(1);
  const [toValue, setToValue] = useState(convert(1).from(fromUnit).to(toUnit));

  const updateFromUnit = (event) => {
    setFromUnit(() => event.target.value);
    setToValue(() => convert(fromValue).from(event.target.value).to(toUnit));
  };

  const updateToUnit = (event) => {
    setToUnit(() => event.target.value);
    setToValue(() => convert(fromValue).from(fromUnit).to(event.target.value));
  };

  const updateValue = (event) => {
    setFromValue(() => event.target.value);
    setToValue(() => convert(event.target.value).from(fromUnit).to(toUnit));
  };

  return <div className="converter">
      <Select label="From:" options={possibilities} onChange={updateFromUnit}></Select>
      <Select label="To:" options={possibilities} onChange={updateToUnit}></Select>
      <Input label="Value:" type="floating-point" onChange={updateValue}></Input>
      <p>{fromValue} {fromUnit} = {toValue} {toUnit}</p>
  </div>
};

Converter.propTypes = {
  measure: PropTypes.string.isRequired
};

Input.defaultProps = {
  measure: 'length'
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Компонент принимает одно свойство measure, которое определяет тип единиц, подлежащих преобразованию, и может быть чем-то вроде mass или length. Код этого компонента состоит из четырех частей. Первое действие — это запрос к библиотеке convert-units для всех возможных вариантов преобразования единиц измерения. Единицы измерения отображаются в массив объектов, готовых к использованию компонентом Select. В следующей части вы определите четыре свойства состояния, а затем три обработчика событий. Они будут реагировать на изменение пользовательского ввода и соответствующим образом обновлять состояние. Эти обработчики событий содержат фактические вызовы библиотеки convert-units, где происходит преобразование единиц измерения. Наконец, компонент собирается из всех частей и возвращается. Вы также можете создать историю для этого более сложного компонента с отдельными компонентами. Создайте файл src/stories/Converter.stories.jsx и вставьте в него следующее содержимое.

import React from 'react';
import { Converter } from './Converter';

export default {
  title: 'Components/Converter',
  component: Converter,
};

const Template = (args) => <Converter {...args} />;

export const Default = Template.bind({});

Default.args = {
  measure: 'length'
};

export const Mass = Template.bind({});

Mass.args = {
  measure: 'mass'
};
Вход в полноэкранный режим Выход из полноэкранного режима

Когда вы устанавливали Storybook с помощью команды npx sb, сценарий инициализации добавил несколько компонентов в качестве примеров для демонстрации возможностей Storybook. Вы будете повторно использовать два из этих компонентов для приложения преобразования единиц.
Откройте src/stories/Header.jsx и замените его содержимое следующим кодом.

import React from 'react';
import PropTypes from 'prop-types';
import { Button } from './Button';
import './header.css';

export const Header = ({ user, onLogin, onLogout }) => (
  <header>
    <div className="wrapper">
      <div>
        <h1>Unit Converter</h1>
      </div>
      {user ? <div> Hello {user.given_name} </div> : ""}
      <div>
        {user ? (
          <Button size="small" onClick={onLogout} label="Log out" />
        ) : (
          <>
            <Button size="small" onClick={onLogin} label="Log in" />
          </>
        )}
      </div>
    </div>
  </header>
);

Header.propTypes = {
  user: PropTypes.shape({}),
  onLogin: PropTypes.func.isRequired,
  onLogout: PropTypes.func.isRequired,
  onCreateAccount: PropTypes.func.isRequired,
};

Header.defaultProps = {
  user: null,
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Я изменил компонент заголовка, чтобы он показывал правильное название приложения и позволял передавать некоторые структурированные данные пользователя. В истории для заголовка, в файле src/stories/Header.stories.jsx, измените аргументы, передаваемые в историю LoggedIn, чтобы отразить это изменение.

LoggedIn.args = {
  user: {
    given_name: "Username"
  },
};
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь откройте src/stories/Page.jsx и измените его содержимое в соответствии с приведенным ниже кодом.

import React from 'react';
import PropTypes from 'prop-types';
import { Header } from './Header';
import './page.css';
import { Tabs } from './Components';
import { Converter } from './Converter';

export const Page = ({useAuth}) => {
  const [user, login, logout] = useAuth();
  return <article>
    <Header user={user} onLogin={login} onLogout={logout} />
    <section>
      <Tabs>
        <Converter measure="length" label="Length" key="length"></Converter>
        <Converter measure="mass" label="Mass" key="mass"></Converter>
        <Converter measure="volume" label="Volume" key="volume"></Converter>
      </Tabs>
    </section>
  </article>;
}

Page.propTypes = {
  useAuth: PropTypes.func.isRequired
};

Page.defaultProps = {
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Этот компонент отображает страницу приложения, включая заголовок и контейнер с вкладками, который позволяет переключаться между компонентами Converter, настроенными на преобразование различных мер. На странице необходимо передать хук useAuth, который возвращает информацию о пользователе и обратные вызовы для входа или выхода пользователя. В истории для страницы, в src/stories/Page.stories.jsx, нужно создать имитационную функцию, которая предоставляет поддельные данные пользователя. Отредактируйте содержимое этого файла, чтобы оно выглядело как следующий код.

import React from 'react';
import { Page } from './Page';

export default {
  title: 'Pages/Page',
  component: Page,
};

const mockUseAuth = (loggedIn) => () => [
  loggedIn ? {given_name: "Username"} : undefined, 
  () => {}, 
  () => {}
];

const Template = (args) => <Page useAuth={mockUseAuth(true)} {...args}/>;

export const LoggedIn = Template.bind({});
LoggedIn.args = {
  useAuth: mockUseAuth(true),
};

LoggedIn.parameters = {
  controls: { hideNoControlsWarning: true },
};

export const LoggedOut = Template.bind({});
LoggedOut.args = {
  useAuth: mockUseAuth(false),
};

LoggedOut.parameters = {
  controls: { hideNoControlsWarning: true },
};
Вход в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, как mockUseAuth использует currying для возврата функции, которая может быть использована в качестве крючка useAuth в компоненте Page. Теперь вы можете снова использовать Storybook для тестирования компонента Converter и полной страницы приложения. Если он все еще не запущен, запустите npm run storybook снова. Вы можете перейти в раздел Pages -> Page в левой боковой панели, и вы должны увидеть что-то похожее на изображение ниже.

Добавление аутентификации с помощью Okta в приложение

Вы создали страницу, которая использует хук useAuth для управления аутентификацией пользователей. Для историй Storybook вы создали имитационную реализацию этого крючка. В этом разделе мы покажем вам, как реализовать хук с помощью службы аутентификации Okta. Сначала зарегистрируйте приложение в Okta.

Прежде чем начать, вам понадобится бесплатная учетная запись разработчика Okta. Установите Okta CLI и выполните команду okta register, чтобы зарегистрировать новую учетную запись. Если у вас уже есть учетная запись, выполните команду okta login. Затем выполните команду okta apps create. Выберите имя приложения по умолчанию или измените его по своему усмотрению. Выберите Одностраничное приложение и нажмите Enter.

Используйте http://localhost:3000/callback для URI перенаправления и установите URI перенаправления выхода http://localhost:3000.

Что делает Okta CLI?

Okta CLI создаст OIDC Single-Page App в вашей Okta Org. Он добавит указанные вами URI перенаправления и предоставит доступ группе Everyone. Он также добавит доверенное происхождение для http://localhost:3000. По окончании работы вы увидите результат, подобный следующему:

Okta application configuration:
Issuer:    https://dev-133337.okta.com/oauth2/default
Client ID: 0oab8eb55Kb9jdMIr5d6
Вход в полноэкранный режим Выход из полноэкранного режима

ПРИМЕЧАНИЕ: Вы также можете использовать консоль администратора Okta для создания приложения. Дополнительную информацию смотрите в разделе Создание приложения React.

Далее установите необходимые библиотеки. Откройте терминал и выполните приведенную ниже команду.

npm install -E @okta/okta-react@6.4.1 @okta/okta-auth-js@5.10.0 react-dom@17.0.2 react-router-dom@5.3.0
Войти в полноэкранный режим Выйти из полноэкранного режима

Откройте файл src/index.js и измените его содержимое в соответствии с приведенным ниже кодом.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { App } from './App';
import { Page } from './stories/Page';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter as Router, Route, useHistory } from 'react-router-dom';
import { LoginCallback, SecureRoute, Security } from '@okta/okta-react';
import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js';
import { useAuth } from './auth';

const oktaAuth = new OktaAuth({
  issuer: 'https://{yourOktaDomain}/oauth2/default',
  clientId: '{clientID}',
  redirectUri: `/callback`,
});

function SecuredRoutes(props) {
  const history = useHistory();
  const restoreOriginalUri = async (_oktaAuth, originalUri) => {
    history.replace(toRelativeUrl(originalUri || '/', window.location.origin));
  };

  return (
    <Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
      <Route path="/" exact render={(props) => <App {...props} useAuth={useAuth}/>} />
      <SecureRoute path="/converter" exact render={(props) => <Page {...props} useAuth={useAuth}/>} />
      <Route path="/callback" component={LoginCallback} />
    </Security>
  );
}

ReactDOM.render(
  <React.StrictMode>
    <Router>
      <SecuredRoutes />
    </Router>
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();
Войти в полноэкранный режим Выход из полноэкранного режима

Здесь {yourClientID} — это ID клиента, который вы получили ранее, а {yourOktaDomain} — это ваш домен Okta. Это изменение делает несколько вещей. Экземпляр oktaAuth предоставляет глобальный синглтон аутентификации. Основная функция render теперь содержит элемент Router, который позволяет приложению перемещаться по различным маршрутам. Наконец, SecuredRoutes — это компонент, который оборачивает маршруты в компонент Security. Этот компонент делает хук useOktaAuth доступным для всех компонентов, содержащихся в нем. Внутри этого компонента вы определяете маршруты. Обратите внимание, как вы передаете хук useAuth в компоненты App и Page. Создайте новый файл src/auth.js и добавьте следующий код для реализации этого хука.

import { useEffect, useState } from 'react';
import { useOktaAuth } from '@okta/okta-react';

export const useAuth = () => {
  const { oktaAuth, authState } = useOktaAuth();
  const [user, setUser] = useState(null);

  useEffect(() => {
    if (authState?.isAuthenticated) {
      if (!user) {
        oktaAuth.getUser().then(setUser);
      }
    } else {
      setUser(null);
    }
  }, [authState, user, oktaAuth]);

  const login = async () => oktaAuth.signInWithRedirect('/');
  const logout = async () => oktaAuth.signOut('/');

  return [user, login, logout];
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Наконец, вам нужно изменить существующий компонент App, чтобы использовать крючок аутентификации. Откройте src/App.js и настройте содержимое так, чтобы оно выглядело следующим образом.

import './App.css';
import { Link } from 'react-router-dom';
import { Header } from './stories/Header';

export const App = ({useAuth}) => {
  const [user, login, logout] = useAuth();

  return (
    <div className="App">
      <Header user={user} onLogin={login} onLogout={logout} />
      <h1>Unit Converter</h1>
      <p>
      <Link to="/converter">Go to the app!</Link>
      </p>
    </div>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Поздравляем, вы завершили работу над своим React-приложением с Storybook. Теперь вы можете открыть консоль в папке проекта и выполнить следующую команду для запуска приложения.

npm start
Войти в полноэкранный режим Выйти из полноэкранного режима

В браузере должна появиться первая страница приложения. Когда вы нажмете на ссылку «Перейти к приложению!», вы войдете на страницу Okta. После успешного входа вы будете перенаправлены на страницу конвертера единиц измерения, которая выглядит как показано на рисунке ниже.

Узнайте больше о React, Storybook и одностраничных приложениях

В этом руководстве я показал вам, как создать приложение React и использовать Storybook для просмотра компонентов приложения. Storybook — это отличный инструмент, который может улучшить ваш рабочий процесс разработки.

  • Он позволяет просматривать и тестировать компоненты в изоляции.
  • Вы можете указать расположение каждого компонента в иерархическом меню, а затем просматривать компоненты в браузере.
  • Вы можете иметь несколько историй, демонстрирующих различные варианты использования каждого компонента.
  • Вы также можете изменять параметры компонентов и видеть их влияние на внешний вид в режиме реального времени.
  • Storybook может работать во время процесса разработки, и в нем будут отражаться все изменения, которые вы вносите в код.

Приложение, которое вы написали, было простым приложением для преобразования блоков. Я подсказал вам, как использовать библиотеку convert-units для преобразования длины, массы и объема. Вы собрали отдельные компоненты, чтобы создать более крупный компонент, содержащий несколько элементов ввода. Я показал вам, как Storybook позволяет создавать истории, тестировать эти сложные компоненты и заполнять страницы приложений.

Если вы хотите узнать больше о любой из этих тем, перейдите по ссылкам ниже.

  • Создание приложения React с помощью стилизованных компонентов
  • Лучшие инструменты тестирования для Node.js
  • Построение простого приложения React с использованием крючков
  • Разработка безопасных приложений с помощью WebSockets и Node.js

Код для этого руководства вы можете найти на GitHub.

oktadev / okta-react-storybook-example

React-приложение с использованием Storybook

Если вам понравился этот учебник, есть вероятность, что вам понравятся и другие, которые мы публикуем. Пожалуйста, следите за @oktadev в Twitter и подписывайтесь на наш канал YouTube, чтобы получать уведомления о публикации новых уроков для разработчиков.


Оригинальное сообщение написано Хольгером Шмитцем для блога Okta Developer.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *