Начало работы с сборником рассказов в React

Вы когда-нибудь пытались разместить все свои компоненты пользовательского интерфейса в одном месте в React?

Если вы новичок в мире React, то, вероятно, не будете.

Что это значит?

См. реагировать-красиво-dnd Примеры.

То, что вы видели в примерах, называется историями. И инструмент, который используется для создания историй, называется Storybook.

Теперь вы поняли, о чем мы будем говорить в этой статье. Без лишних слов давайте исследовать.

Что такое сборник рассказов?

Storybook — это изолированная среда разработки с пользовательским интерфейсом, которая предоставляет игровую площадку для ваших компонентов. Мы можем играть с нашими компонентами по-разному, не запуская наше основное приложение. Мы можем запустить сборник рассказов в его порту с настройкой.

Это не ограничивается React. Мы можем использовать сборник рассказов с большинством интерфейсных фреймворков, таких как Vue, Angular, Mithril, Marko, Svelte и т. д.,

Вы можете узнать больше о сборнике рассказов здесь.

Что такое история?

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

Допустим, у нас есть компонент Button.

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

Вы можете увидеть истории кнопки в разных случаях (большой, средний, маленький).

Настройка сборника рассказов в проекте

Мы настроим сборник рассказов в реактивном проекте.

Пойдем.

  • Создайте проект реакции с помощью следующей команды. Вы можете назвать как угодно.
npx create-react-app storybook-demo
  • Теперь установите сборник рассказов в свой проект с помощью следующей команды.
npx sb init

Мы завершили настройку сборника рассказов.

Сборник историй предоставляет нам отдельный сервер.

Как начать?

Сборник рассказов автоматически добавляет команду в наш файл сценария. Вы можете проверить это в файле package.json в разделе скриптов. А пока выполните следующую команду, чтобы запустить сервер сборника рассказов.

npm run storybook

Storybook запустит новый сервер с портом, указанным в разделе сценариев файла package.json. Он автоматически откроет сборник рассказов в нашем браузере по умолчанию (так же, как и сервер реагирования).

По умолчанию вы увидите в нем разные истории. Вы можете удалить их, если не хотите, или оставить для справки. Как мы обсуждали в предыдущем разделе, у кнопки может быть несколько состояний, вы можете увидеть их в сборнике рассказов (упомянуты не все состояния). Мы собираемся написать большой набор историй для кнопки в последнем разделе этого урока.

Исследуйте разные разделы сборника рассказов и ознакомьтесь с другим разделом. В этом уроке мы рассмотрим некоторые из них.

Давайте напишем нашу первую историю.

Сборник рассказов о тестировании

Мы видели работающий сборник рассказов и несколько примеров в нем.

  • Создайте папку с именем Button внутри папки src.
  • Создайте файлы с именами Button.jsx, Button.css и Constants.js.
  • Поместите соответствующий код из приведенных ниже фрагментов в файлы.

Кнопка.jsx

import React, { Component } from "react";
import PropTypes from "prop-types";

import "./Button.css";

import { buttonTypes, buttonVariants, buttonSizes } from "./constants";

class Button extends Component {
    static defaultProps = {
        isDisabled: false,
        type: "filled",
        variant: "oval",
        size: "medium",
        backgroundColor: "#1ea7fd",
        textColor: "#ffffff",
    };

    static buttonTypes = buttonTypes;
    static buttonVariants = buttonVariants;
    static buttonSizes = buttonSizes;

    renderButton = () => {
        const {
            text,
            isDisabled,
            type,
            variant,
            size,
            backgroundColor,
            textColor,
            onClick,
        } = this.props;
        return (
            <button
                onClick={onClick}
                className={`default ${variant} ${size} ${
                    isDisabled ? "disabled" : ""
                }`}
                style={
                    type === buttonTypes.outline
                        ? {
                              border: `1px solid ${backgroundColor}`,
                              color: "#000000",
                              backgroundColor: "transparent",
                          }
                        : {
                              backgroundColor: `${backgroundColor}`,
                              border: `1px solid ${backgroundColor}`,
                              color: textColor,
                          }
                }
                disabled={isDisabled}
            >
                {text}
            </button>
        );
    };

    render() {
        return this.renderButton();
    }
}

Button.propTypes = {
    text: PropTypes.string,
    isDisabled: PropTypes.bool,
    type: PropTypes.oneOf([buttonTypes.outline, buttonTypes.filled]),
    variant: PropTypes.oneOf([buttonVariants.oval, buttonVariants.rectangular]),
    size: PropTypes.oneOf([
        buttonSizes.small,
        buttonSizes.medium,
        buttonSizes.large,
    ]),
    backgroundColor: PropTypes.string,
    textColor: PropTypes.string,
    onClick: PropTypes.func,
};

export { Button };

Кнопка.css

.default {
    border: none;
    cursor: pointer;
    background-color: transparent;
}

.default:focus {
    outline: none;
}

.disabled {
    opacity: 0.75; 
    cursor: not-allowed;
}
.small {
    font-size: 12px;
    padding: 4px 8px;
}

.medium {
    font-size: 14px;
    padding: 8px 12px;
}

.large {
    font-size: 16px;
    padding: 12px 16px;
}

.oval {
    border-radius: 4px;
}

.rectangular {
    border-radius: 0;
}

константы.js

export const buttonTypes = {
    outline: "outline",
    filled: "filled",
};

export const buttonVariants = {
    oval: "oval",
    rectangular: "rectangular",
};

export const buttonSizes = {
    small: "small",
    medium: "medium",
    large: "large",
};

Что это за код?

Мы написали общий компонент для Button, который можно использовать по-разному. Теперь у нас есть компонент, который может иметь разные состояния.

Давайте напишем нашу первую историю, выполнив следующие шаги.

  • Создайте файл с именем Button.stories.jsx.
  • Импортируйте React и наш компонент Button в файл.
  • Теперь определите название или путь к нашей составной истории. Мы определим его, используя следующий код.
export default {
   title: ‘common/Button’,
}

Приведенный выше код поместит все истории, находящиеся в текущем файле, в каталог common/Button/.

  • Экспортируйте кнопку с обязательным реквизитом следующим образом.
export const defaultButton = () => (
    <Button text=”Default Button” onClick={() => {}} />
);

Мы закончили нашу первую историю. Запустите сборник рассказов с помощью следующей команды и посмотрите результат.

npm run storybook

Мы напишем еще историй, в конце концов, не волнуйтесь.

Чем это полезно во фронтенд-разработке?

В чем главное преимущество использования сборника рассказов?

Допустим, мы работаем в команде из 10 человек. И нам нужно проверить общие компоненты, которые все написали для текущего рабочего проекта.

Как мы можем сделать это?

Мы должны перейти к каждому общему компоненту, чтобы проверить их. Но это отнимает много времени и не является для нас предпочтительным способом. А вот и наш новый гостевой сборник рассказов.

Как использовать его для решения нашей проблемы?

Мы можем писать истории для общих компонентов (любых компонентов пользовательского интерфейса), используя сборник рассказов. И всякий раз, когда ваш товарищ по команде хочет проверить общие компоненты других, он просто запускает сервер сборника рассказов и увидит там все компоненты пользовательского интерфейса, как мы видели выше.

Мы можем сделать гораздо больше с визуализированными компонентами в сборнике рассказов. В Storybook есть концепция Addons, которая придает нашим историям сверхспособности.

Допустим, нам нужно проверить отзывчивость компонентов пользовательского интерфейса в самом сборнике рассказов, мы можем использовать надстройку под названием Viewport в сборнике рассказов. Мы узнаем больше об аддонах в следующих разделах.

Работа со сборником рассказов

В этом разделе мы напишем разные истории, определяющие разные состояния нашего общего компонента Button.

Писать рассказы не так уж и сложно. История определяет состояние компонента. Если вы видите свойства компонента, вы легко поймете различные варианты использования компонента.

Давайте напишем несколько историй, предоставив необязательный реквизит.

export const largeButton = () => (
    <Button text="Large Button" onClick={() => {}} size="large" />
);
export const outlineSmallButton = () => (
    <Button
        text="Outline Small Button"
        onClick={() => {}}
        size="small"
        type="outline"
    />
);
export const rectangularLargeButton = () => (
    <Button
        text="Rectangular Large Button"
        onClick={() => {}}
        size="large"
        variant="rectangular"
    />
);


export const disabledButton = () => (
    <Button text="Disabled Button" onClick={() => {}} isDisabled={true} />
);


export const warningButton = () => (
    <Button
        text="Warning Button"
        onClick={() => {}}
        backgroundColor="orange"
    />
);

Вышеприведенные три истории определяют различные варианты использования нашего компонента Button. Теперь ваша очередь добавить несколько других кейсов историй для нашего общего компонента. Попробуйте добавить disabledSamllRectangularButton,hazardButton, SuccessDisabledButton и т. д.,

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

import React from "react";

import { Button } from "./Button";

export default {
    title: "src/common/Button",
};

export const defaultButton = () => (
    <Button text="Default Button" onClick={() => {}} />
);

export const largeButton = () => (
    <Button text="Large Button" onClick={() => {}} size="large" />
);

export const outlineSmallButton = () => (
    <Button
        text="Outline Small Button"
        onClick={() => {}}
        size="small"
        type="outline"
    />
);

export const rectangularLargeButton = () => (
    <Button
        text="Rectangular Large Button"
        onClick={() => {}}
        size="large"
        variant="rectangular"
    />
);

export const disabledButton = () => (
    <Button text="Disabled Button" onClick={() => {}} isDisabled={true} />
);

export const warningButton = () => (
    <Button
        text="Disabled Button"
        onClick={() => {}}
        backgroundColor="orange"
    />
);

Теперь вы получили полный контроль над написанием историй для компонента.

Давайте перейдем к следующему разделу, где мы узнаем об дополнениях и о том, как они улучшают наши истории.

Дополнения сборника рассказов

По умолчанию у нас будет несколько дополнений. В разделе мы рассмотрим самые полезные аддоны для нашей разработки.

Давайте продвинем наши истории о кнопках.

Элементы управления

Элементы управления добавляют функцию для предоставления пользовательских реквизитов компоненту в самой книге рассказов. Для нашего компонента Button мы можем добавить элементы управления для изменения различных реквизитов в сборнике рассказов.

Допустим, нам нужно найти лучший цвет для фона кнопки. Это займет много времени, если мы протестируем его, чтобы проверить цвет фона, давая один за другим компоненту. Вместо этого мы можем добавить элемент управления, который позволяет нам выбирать другой цвет в сборнике рассказов. Мы можем проверить цвет фона в самом сборнике рассказов.

Давайте посмотрим, как добавить элементы управления в наши истории с кнопками.

Во-первых, мы должны определить все реквизиты под заголовком следующим образом.

export default {
    title: "src/common/Button",
    argTypes: {
        text: { control: "text" },
        backgroundColor: { control: "color" },
        isDisabled: { control: "boolean" },
        size: {
            control: { type: "select", options: ["small", "medium", "large"] },
        },
        type: {
            control: { type: "select", options: ["filled", "outline"] },
        },
        variant: {
            control: { type: "select", options: ["oval", "rectangular"] },
        },
    },
};

Затем отделите свойства от компонента и передайте их в качестве аргументов следующим образом.

export const outlineSmallButton = (args) => (
    <Button {...args} onClick={() => {}} />
);
outlineSmallButton.args = {
    text: "Outline Small Button",
    size: "small",
    type: "outline",
};

Вы можете увидеть элементы управления в нижней части окна предварительного просмотра компонента.

Вы можете увидеть вкладку управления в нижней части окна предварительного просмотра компонента. Поиграйте с этим.

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

Обновленные истории кнопок будут выглядеть следующим образом.

import React from "react";

import { Button } from "./Button";

export default {
    title: "src/common/Button",
    argTypes: {
        text: { control: "text" },
        backgroundColor: { control: "color" },
        isDisabled: { control: "boolean" },
        size: {
            control: { type: "select", options: ["small", "medium", "large"] },
        },
        type: {
            control: { type: "select", options: ["filled", "outline"] },
        },
        variant: {
            control: { type: "select", options: ["oval", "rectangular"] },
        },
    },
};

export const defaultButton = (args) => <Button {...args} onClick={() => {}} />;
defaultButton.args = {
    text: "Default Button",
};

export const largeButton = (args) => (
    <Button {...args} onClick={() => {}} size="large" />
);
largeButton.args = {
    text: "Large Button",
};

export const outlineSmallButton = (args) => (
    <Button {...args} onClick={() => {}} />
);
outlineSmallButton.args = {
    text: "Outline Small Button",
    size: "small",
    type: "outline",
};

export const rectangularLargeButton = (args) => (
    <Button {...args} onClick={() => {}} />
);
rectangularLargeButton.args = {
    text: "Rectangular Large Button",
    size: "large",
    variant: "rectangular",
};

export const disabledButton = (args) => <Button {...args} onClick={() => {}} />;
disabledButton.args = {
    text: "Disabled Button",
    isDisabled: true,
};

export const warningButton = (args) => <Button {...args} onClick={() => {}} />;
warningButton.args = {
    text: "Warning Button",
    backgroundColor: "orange",
};

Действия

Действия — это события в JavaScript. Мы можем нажать кнопку, которая является событием в JavaScript. Мы можем выполнять некоторые действия по нажатию кнопки, используя аддон действий.

С помощью действий мы можем проверить, правильно ли работают события. Кнопка «Отключено» не может быть нажата, а кнопка «Включено» должна быть доступна для нажатия. Мы можем обеспечить это с помощью действий.

Давайте посмотрим, как добавить действие к нажатию кнопки.

Ранее мы предоставили анонимную функцию свойствам onClick. Теперь мы должны обновить его.

  • Импортируйте действие из надстройки сборника рассказов, используя следующую инструкцию.
import { action } from "@storybook/addon-actions";
  • Замените все () => {} следующим утверждением.
action("Button is clicked!")

Теперь перейдите к сборнику рассказов и нажмите кнопку. Вы увидите сообщение, напечатанное на вкладке действий, которая находится рядом с вкладкой элементов управления. Сообщение не будет напечатано, если вы нажмете отключенную кнопку, поскольку она отключена.

Мы можем использовать действие для различных событий, таких как onChange, onMouseOver, onMouseOut и т. д., чтобы убедиться, что они работают правильно. Попробуйте реализовать то же самое для onChange для элемента ввода.

См. документацию для действий здесь.

Фон

Мы можем изменить фон окна предварительного просмотра, используя фоновый аддон. Нам не нужно писать код. Просто измените его в сборнике рассказов. Вы можете увидеть гифку ниже.

Область просмотра

Мы также можем проверить отзывчивость наших компонентов в сборнике рассказов. Посмотрите гифку ниже, чтобы узнать об опциях области просмотра.

Документы

Мы можем задокументировать наши компоненты в сборнике рассказов с помощью надстройки docs. Это полезнее, когда мы работаем в команде. Они будут читать компонент и понимать его напрямую. Это экономит много времени разработчикам.

В окне предварительного просмотра компонентов сборников рассказов вы можете увидеть Документы в правом верхнем углу на вкладке Холст. Он будет содержать все документы всех историй компонента. Мы должны использовать Button.stories.mdx, если мы хотим задокументировать компонент, который включает как уценку, так и рендеринг компонента. Мы просто пишем дополнительный код уценки внутри него вместе с историями компонентов.

Мы пишем документ для наших историй. Код включает уценку и рендеринг компонентов. Это всего лишь изучение синтаксиса. Вы поймете это с первого взгляда.

Давайте посмотрим код документа Button.stories.mdx.

<!--- Button.stories.mdx -->

import {
    Meta,
    Story,
    Preview,
    ArgsTable
} from '@storybook/addon-docs/blocks';

import { Button } from './Button';

<Meta title="MDX/Button" component={Button} />

# Button Documentation

With `MDX` we can define a story for `Button` right in the middle of our
Markdown documentation.

<ArgsTable of={Button} />

export const Template = (args) => <Button {...args} />

## Default Button
We can write the documentation related to the Default Button
<Preview>
    <Story name="Default Button" args={{
        text: 'Default Button'
    }}>
    {Template.bind({})}
   </Story>
</Preview>

## Large Button
We are writing sample docs for two stories, you can write rest of them
<Preview>
    <Story name="Large Button" args={{
        text: "Large Button",
        }}>
        {Template.bind({})}
    </Story>
</Preview>

Узнайте больше о компонентах документирования здесь.

Вы можете узнать больше о дополнениях здесь.

Вывод

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

Новичок в Реагировании? Ознакомьтесь с этими учебными ресурсами.

Удачного кодирования 🙂