Allysson Santos

Front-end Developer

Criando uma lib de componentes React - Parte 1

Introdução:

Nessa primeira parte iremos criar o repositório no github, instalar, configurar e entender como funciona o storybook, também iremos adicionar as demais dependências do projeto.

Criando uma lib de componentes React - Parte 1

Nessa série de posts iremos criar uma biblioteca de componentes bem completa! Criaremos desde o repositório no github até a publicação automatizada no NPM via TravisCI.

Iremos abordar assuntos como:

  • Tematização;
  • Tree-shaking;
  • Versionamento;
  • Estrutura;
  • CSS-in-JS;
  • Linter;
  • Testes;
  • Deploy;
  • CI/CD;
  • Padronização de commits
  • etc…

Também conheceremos algumas ferramentas para nos ajudar com o desenvolvimento, build e deploy. Como por exemplo:

Criando repositório no GitHub

Por mais simples que seja, precisamos começar criando o repositório de nossa biblioteca no github. Primeiramente você precisa ter um usuário no github, se ainda não tiver, vá criar agora! (https://github.com/join).

Após logado, crie um novo repositório, escolha o nome da sua biblioteca, no meu caso, será “frigobar”. Coloque também uma descrição para o projeto, escolha se é privado ou público (é claro que será público, né? você usa trocentos projetos open-source, porque sua biblioteca não seria??). É bom já iniciar com um README.md, um .gitignore e adicionar uma licença, e é claro que será MIT.

Imagem do formulário de novo projeto do github preenchido

Após criado, clone seu projeto!

Imagem do pop-over para clonar o projeto do github

git clone [email protected]:SEU-USUARIO/SEU-PROJETO.git

Percebeu que ele veio com o .gitignore, README.md e LICENSE? Foi porque selecionamos no formulário do github. O .gitignore já vem preenchido com alguns arquivos comumente ignorados para a stack de node, ele já contempla todos os arquivos que precisaremos ignorar, como por exemplo, node_modules, yarn-error, etc.

Pronto! já temos nosso repositório criado e clonado em nossa máquina.

Iniciando o desenvolvimento

Primeiramente, iremos criar nosso package.json. Para isso, abra o terminal e vá até a pasta do seu projeto que você clonou. Rode npm init, responda as perguntas, (o test command pode ficar em branco mesmo). No meu caso ficou assim:

Imagem CLI do npm init Isso irá gerar nosso package.json.

Agora vamos instalar nossas primeiras dependências para criação de nossa biblioteca. Primeiramente, vamos instalar o react e o react-dom.

1
npm install react react-dom

Após a instalação, as duas dependências serão adicionadas no package.json:

Imagem do package.json mostrando o react e react-dom como dependências

Mais pra frente veremos que o react e o react-dom não devem ficar nesse nó de dependencies no package.json.

Storybook

Agora, pra gente não precisar criar uma aplicação pra conseguir visualizar os componentes que iremos criar, e também pra dar um certo tipo de documentação pra quem quiser visualizar quais componentes nossa lib disponibiliza, iremos utilizar o Storybook. Ele é uma ferramenta para desenvolver componentes visuais em React, Vue e Angular, ele mantém a visualização de seus componentes organizada e eficiente.

Essa é a cara do storybook: Imagem da interface do storybook Pra gente instalar, basta rodar:

1
npx -p @storybook/cli sb init

A instalação do Storybook vai detectar que estamos utilizando React e vai instalar a versão pro framework correto. Após o término da instalação vamos rodar:

1
npm run storybook

E se tudo der certo vamos ver a mensagem para acessar nosso storybook local:

Imagem da mensagem de que o storybook esta rodando

Acessando https://localhost:6006/ veremos o nosso próprio storybook!

Imagem do storybook local

Perceba que o storybook criou alguns arquivos no root do projeto:

1
2
3
4
5
6
7
8
9
10
├── .gitignore
├── LICENSE
├── package.json
├── package-lock.json
├── README.md
├── stories /* Essa*/
│   └── index.stories.js
└── .storybook /* E essa */
    ├── addons.js
    └── config.js

A pasta stories é a pasta default onde o storybook procura suas histórias. Uma história geralmente é a representação de um estado de um componente, perceba também que já temos duas histórias no index.stories.js, vamos analisar o conteúdo do index.stories.js.

Vamos dar uma olhada no que é importado dentro do arquivo:

1
2
3
4
5
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';

import { Button, Welcome } from '@storybook/react/demo';

storiesOf

Função que inicia a criação da história, ela recebe dois parâmetros, o primeiro é o nome do conjunto de histórias que será exibido no painel esquerdo, chamado de kind. O segundo parâmetro é o module, uma variável global declarada pelo próprio storybook que é necessária para criar uma referência ao arquivo que sua história está. Essa referência serve para habilitar o hot-module-replacement. Sem ela você teria que dar um refresh na página toda vez que editasse sua história.

storiesOf().add()

O add(name, functionalComponent) recebe dois parâmetros também, o primeiro é o nome da história em questão, chamado de story, o segundo é uma função que retorna o componente React que será exibido quando essa história for selecionada. Podem existir inúmeros .add() encadeados no mesmo storiesOf.

action & linkTo

Como você pode perceber, o action e o linkTo estão sendo importados como plugins, o storybook possui vários plugins para dar algumas funcionalidades a mais à sua história, você pode conferir alguns no próprio site do storybook.

Button & Welcome

São componentes React comuns, estão ali apenas para popular as histórias que vem por padrão.

Estrutura de uma história

Bom, para criar uma história basta seguir como no exemplo da história do Button. Edite a história que vem por default para ver os efeitos que são aplicados no storybook. O código editado deve ficar assim:

1
2
3
4
5
6
7
8
9
10
11
storiesOf('História do Button', module) /*  alterado para "História do Button"*/
  .add('Com um texto de Hello Button', () => ( /*  alterado para "Com um texto de Hello Button"*/
    <Button onClick={action('HelloButton clicked')}>Hello Button</Button>
  ))
  .add('Com alguns emojis', () => ( /*  alterado para "Com alguns emojis"*/
    <Button onClick={action('EmojiButton clicked')}>
      <span role="img" aria-label="so cool">
        😀 😎 👍 💯
      </span>
    </Button>
  ));

Esse trecho de código editou as duas stories do kind “História do Button” como podemos ver no gif a seguir:

Gif das histórias editadas

A pasta .storybook

Você também deve ter percebido que surgiu uma pasta .storybook no seu projeto. As configurações de carregamento das stories, addons e webpack ficam aqui. O storybook possuí um webpack por baixo dos panos, caso você queira editar alguma configuração, basta criar um arquivo webpack.config.js nessa pasta e sobrescrever o que necessita ser alterado. Você pode ver melhor aqui: https://storybook.js.org/docs/configurations/custom-webpack-config/.

O arquivo config.js está basicamente importando todos os arquivos que terminam com .stories.js do diretório /stories/ e carregando todas as stories que esses arquivos contêm. Atualmente o arquivo addons.js está registrando dois addons, o actions e links, vamos ver o que esses addons fazem.

actions

O addon actions está sendo usado na story que vem por default, do kind Button na story “Com um texto de Hello Button”. No caso, ele está sendo usado no onClick do Button, como você pode ver a seguir: Addon action

Ao abrir a story “Com um texto de Hello Button” perceba que há um painel chamado Actions na parte inferior da página, ao clicar no botão que está sendo exibido na story ,serão logados as informações do evento de click na aba de Actions: Actions onClick log

O addon actions deve ser usado para exibir os dados recebidos por event-handlers no storybook, como onClick, onKeyDown, etc. Se você quiser saber mais sobre o funcionamento desse addon, veja o github do projeto.

Como o próprio nome diz, o addon links serve para linkar stories entre sí. Na story do componente <Welcome /> que vem por default, há um link que deveria linkar para a story chamada “Button”. Porém, se a gente clicar nesse link veremos que vai dar pau. Se liga:

Problema na história do Button

Ao clicar no link stories, vemos essa mensagem meio bugada No Preview. Isso acontece porque o addon link recebe como primeiro parâmetro o nome do kind e a story como segundo parâmetro. Como mudamos o nome do kind para “História do Button”, esse link não irá mais funcionar.

Vamos renomear o kind de História do Button para apenas “Botao” e alterar o parâmetro da função linkTo da prop showApp do componente <Welcome /> para também ficar “Botao”, assim:

index.stories.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
storiesOf('Welcome', module).add('to Storybook', () => (
  <Welcome showApp={linkTo('Botao')} /> /* alteramos aqui */
));

storiesOf('Botao', module) /* alteramos aqui */
  .add('Com um texto de Hello Button', () => (
    <Button onClick={action('HelloButton clicked')}>Hello Button</Button>
  ))
  .add('Com alguns emojis', () => (
    <Button onClick={action('EmojiButton clicked')}>
      <span role="img" aria-label="so cool">
        😀 😎 👍 💯
      </span>
    </Button>
  ));

Agora, ao clicar no link stories do kind “Welcome” da story “to Storybook” veremos que irá linkar para a primeira story do kind Botão: Gif do link stories funcionando

O segundo parâmetro da função linkTo não é obrigatório, porém, se presente, deve ser o nome de algum story do kind especificado. Caso a gente edite novamente a prop showApp do componente Welcome passando um segundo parâmetro para função linkTo como “Com alguns emojis” veremos que ao clicar no link stories ele nos levará à segunda story, e não mais a primeira:

1
2
3
storiesOf('Welcome', module).add('to Storybook', () => (
  <Welcome showApp={linkTo('Botao', 'Com alguns emojis')} /> /* adicionamos segundo parâmetro */
));

Gif do link stories funcionando com segundo parâmetro

Conclusão

Até agora nós criamos o repositório no github, instalamos o React e o ReactDOM, configuramos e editamos o Storybook.

Vimos todos os arquivos que a instalação do storybook criou e também vimos as funções e plugins desses arquivos.

No próximo post vamos começar a desenvolver alguns componentes, configurar e adicionar testes unitários e criar novas stories no storybook.

comments powered by Disqus