Kom godt i gang med Storybook i React

Har du nogensinde prøvet at placere alle dine UI-komponenter et sted i React?

Hvis du er ny i Reacts verden, så gør du det sandsynligvis ikke.

Hvad menes der med det?

Se den reagere-smuk-dnd eksempler.

Det, du har set i eksemplerne, kaldes historier. Og værktøjet, der bruges til at skabe historier, hedder Storybook.

Nu har du forstået, hvad vi skal tale om i denne artikel. Lad os uden omsvøb gå på opdagelse.

Hvad er Storybook?

Storybook er et brugergrænseflade isoleret udviklingsmiljø, der giver en legeplads for dine komponenter. Vi kan lege med vores komponenter på forskellige måder uden at køre vores hovedapp. Vi kan køre historiebogen i dens havn med opsætningen.

Det er ikke begrænset til React. Vi kan bruge storybook med de fleste frontend-frameworks som Vue, Angular, Mithril, Marko, Svelte osv..,

Du kan finde mere om historiebogen her.

Hvad er en historie?

En historie definerer den gengivne tilstand af din komponent. Hvis vi tager en fælles komponent, kan vi bruge den på forskellige måder med rekvisitter. Vi kan skrive en historie for hver af disse stater.

Lad os sige, at vi har en knap-komponent.

En knap kan eksistere i forskellige tilstande som deaktiveret, indlæsning, primær, sekundær, lille, stor, medium osv.. Hvis vi lister alle tilstande ned, vil det være meget vanskeligt at komme videre i selvstudiet. Jeg tror, ​​du forstår det. Du får det mere, når du begynder at arbejde med historiebogen.

Du kan se historien om knappen i forskellige tilfælde (Large, Medium, Small).

Opsætning af Storybook i et projekt

Vi opsætter en historiebog i et reaktionsprojekt.

Lad os gå.

  • Opret et reaktionsprojekt med følgende kommando. Du kan navngive, hvad du vil.
npx create-react-app storybook-demo
  • Installer nu historiebogen i dit projekt med følgende kommando.
npx sb init

Vi har færdiggjort opsætningen til historiebogen.

Historiebogen giver os en separat server.

Hvordan starter man det?

Historiebogen tilføjer automatisk en kommando i vores script-fil. Du kan tjekke det i filen package.json i scriptsektionen. Indtil videre skal du køre følgende kommando for at starte storybook-serveren.

npm run storybook

Storybook vil starte en ny server med port angivet i scriptsektionen i filen package.json. Den åbner automatisk historiebogen i vores standardbrowser (samme som reaktionsserveren).

Du vil som standard se forskellige historier i den. Du kan fjerne dem, hvis du ikke vil, eller beholde dem til reference. Som vi diskuterede i det foregående afsnit, kan en knap have flere tilstande, du kan se dem i historiebogen (ikke alle tilstande nævnt). Vi skal skrive et stort sæt historier til knappen i det sidste afsnit af denne vejledning.

Udforsk forskellige sektioner af historiebogen og bliv fortrolig med de forskellige sektioner. Vi vil dække nogle af dem i selvstudiet.

Lad os skrive vores første historie.

Test af historiebog

Vi har set historiebogen køre og nogle eksempler i den.

  • Opret en mappe kaldet Button inde i src-mappen.
  • Opret filer kaldet Button.jsx, Button.css og constants.js
  • Indsæt den respektive kode fra nedenstående uddrag i filerne.

Button.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 };

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;
}

constants.js

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

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

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

Hvad er den kode?

  Sådan synkroniserer du videoafspilning på Netflix, når du ser med venner

Vi har skrevet en fælles komponent til Button, der kan bruges på forskellige måder. Nu har vi en komponent, der kan have forskellige tilstande.

Lad os skrive vores første historie ved at følge nedenstående trin.

  • Opret en fil kaldet Button.stories.jsx
  • Importer React og vores Button-komponent til filen.
  • Definer nu en titel eller sti til vores komponenthistorier. Vi vil definere det ved hjælp af følgende kode.
export default {
   title: ‘common/Button’,
}

Ovenstående kode vil placere alle historier i den aktuelle fil i common/Button/-mappen.

  • Eksporter en knap med obligatoriske rekvisitter som følger.
export const defaultButton = () => (
    <Button text=”Default Button” onClick={() => {}} />
);

Vi har afsluttet vores første historie. Kør historiebogen med følgende kommando og se outputtet.

npm run storybook

Vi vil skrive flere historier, i sidste ende, bare rolig.

Hvordan er det nyttigt i frontend-udvikling?

Hvad er den største fordel ved at bruge en historiebog?

Lad os sige, at vi arbejder i et team på 10 medlemmer. Og vi skal tjekke fælles komponenter, som alle har skrevet til det aktuelle arbejdsprojekt.

Hvordan kan vi gøre det?

Vi er nødt til at gå til alle almindelige komponenter for at kontrollere dem. Men det er tidskrævende og ikke en foretrukken måde for os. Her kommer vores nye gæstehistoriebog.

Hvordan kan vi bruge det til at overvinde vores problem?

Vi kan skrive historier til de fælles komponenter (enhver UI-komponenter) ved hjælp af storybook. Og når din holdkammerat ønsker at tjekke andres fælles komponenter, så kører de simpelthen storybook-serveren og vil se alle UI-komponenterne der, som vi har set ovenfor.

Vi kan gøre meget mere med de gengivne komponenter i historiebogen. Storybook har et koncept kaldet Addons, der giver superkræfter til vores historier.

Lad os sige, at vi skal kontrollere reaktionsevnen af ​​UI-komponenterne i selve storybooken, vi kan bruge en tilføjelse kaldet Viewport i storybooken. Vi vil lære mere om tilføjelserne i de kommende afsnit.

Arbejde med Storybook

I dette afsnit vil vi skrive forskellige historier, der definerer forskellige tilstande af vores fælles komponentknap.

At skrive historier er ikke så svært. En historie definerer en komponents tilstand. Hvis du ser rekvisitterne til en komponent, så vil du nemt forstå forskellige anvendelsestilfælde af komponenten.

Lad os skrive nogle historier ved at give valgfri rekvisitter.

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"
    />
);

Ovenstående tre historier definerer forskellige anvendelsestilfælde af vores komponentknap. Nu er det din tur til at tilføje nogle andre sager med historier til vores fælles komponent. Prøv at tilføje disabledSamllRectangularButton, dangerButton, successDisabledButton osv..,

  Forøg din routers WiFi-rækkevidde

Jeg vil ikke give kode til ovenstående tilfælde. Du skal skrive det på egen hånd for at forstå det. Du kan se den komplette historiekode, som vi har skrevet indtil nu.

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"
    />
);

Nu har du fuldt greb om at skrive historier til en komponent.

Lad os springe ind i næste afsnit, hvor vi vil lære om tilføjelser, og hvordan de booster vores historier.

Storybook tilføjelser

Vi har flere tilføjelser tilgængelige som standard. I afsnittet vil vi udforske de mest nyttige tilføjelser til vores udvikling.

Lad os booste vores Button-historier.

Kontrolelementer

Kontrolelementer tilføjer en funktion til at give tilpassede rekvisitter til komponenten i selve historiebogen. Til vores knapkomponent kan vi tilføje kontroller for at ændre de forskellige rekvisitter i historiebogen.

Lad os sige, at vi skal finde ud af den bedste farve til knapbaggrundsfarven. Det vil være tidskrævende, hvis vi tester det for at kontrollere baggrundsfarven ved at give en efter en til komponenten. I stedet kan vi tilføje en kontrol, der giver os mulighed for at vælge den anden farve i historiebogen. Vi kan teste baggrundsfarven i selve historiebogen.

Lad os se, hvordan du tilføjer kontrolelementer til vores Button-historier.

Først skal vi definere alle rekvisitterne under titlen som følger.

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"] },
        },
    },
};

Dernæst skal du adskille rekvisitterne fra komponenten og give dem som argumenter som følger.

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

Du kan se kontrolelementerne nederst i komponentvinduet.

Du kan se kontrolfanen nederst i komponentvinduet. Leg omkring det.

Opdater alle historierne som ovenfor. Dette er mere som at kende syntaksen for storybook-tilføjelserne. I argTypes har vi brugt forskellige typer kontroller. Du kan finde alle kontroller, der er til stede i historiebogen her.

Opdaterede knaphistorier vil se ud som følger.

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",
};

Handlinger

Handlinger er begivenheder i JavaScript. Vi kan klikke på en knap, der er en begivenhed i JavaScript. Vi kan udføre nogle handlinger på knap-klik ved hjælp af handlings-tilføjelsen.

  Sådan fortæller du, om nogen læser din besked i WeChat

Med handlinger kan vi teste, om arrangementerne fungerer korrekt eller ej. Deaktiveret knap kan ikke klikkes, og aktiveret knap skal være klikbar. Vi kan sikre det ved hjælp af handlingerne.

Lad os se, hvordan du tilføjer handling til knapklik.

Vi har tidligere givet anonym funktion til onClick-rekvisitterne. Nu skal vi opdatere det.

  • Importer handlingen fra storybook-tilføjelsen ved at bruge følgende erklæring.
import { action } from "@storybook/addon-actions";
  • Erstat alle () => {} med følgende sætning.
action("Button is clicked!")

Gå nu til historiebogen og klik på en knap. Du vil se meddelelsen udskrevet under handlingsfanen, der er ved siden af ​​kontrolfanen. Meddelelsen udskrives ikke, hvis du klikker på deaktiveret-knappen, da den er deaktiveret.

Vi kan bruge handlingen til forskellige begivenheder som onChange, onMouseOver, onMouseOut osv.. for at sikre, at de fungerer korrekt. Prøv at implementere det samme for onChange for et input-element.

Se dokumentationen for handlinger her.

Baggrund

Vi kan ændre baggrunden for forhåndsvisningsvinduet ved hjælp af baggrundstilføjelsen. Vi behøver ikke at skrive nogen kode. Bare skift det inde i historiebogen. Du kan se gif’en nedenfor.

Udsigtsport

Vi kan også teste reaktionsevnen af ​​vores komponenter i historiebogen. Se gif’en nedenfor for at finde ud af mulighederne for viewport.

Dokumenter

Vi kan dokumentere vores komponenter i historiebogen ved hjælp af docs-tilføjelsen. Det er mere nyttigt, når vi arbejder i et team. De vil læse komponenten og forstå den direkte. Det sparer meget tid for udviklerne.

I storybooks’ komponenters forhåndsvisningsvindue kan du se Docs øverst til højre til fanen Canvas. Det vil indeholde alle dokumenter til alle historierne om en komponent. Vi er nødt til at bruge Button.stories.mdx, hvis vi vil dokumentere for den komponent, der inkluderer både markdown og komponentgengivelse. Vi skriver bare noget ekstra markdown-kode inde i det sammen med komponenthistorierne.

Vi er ved at skrive et dokument til vores historier. Koden inkluderer markdown og komponentgengivelse. Det hele er bare at lære syntaksen. Du får det første øjekast.

Lad os se Button.stories.mdx doc-koden.

<!--- 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>

Få mere at vide om dokumentationskomponenterne her.

Du kan finde ud af mere om tilføjelser her.

Konklusion

Håber du nød selvstudiet og lærte om historiebogen. Og brug det effektivt i dit team for at gøre dit arbejde produktivt.

Ny til React? Tjek disse læringsressourcer.

God kodning 🙂