
Escrito por Kristofer Selbekk , em colaboração com Caroline Odden . Com base em uma palestra com o mesmo nome e com as mesmas pessoas na reunião ReactJS em Oslo em junho de 2019.
Do tradutor - o nome original de Os 10 Mandamentos dos Componentes não menciona React, mas a maioria dos exemplos e recomendações se relaciona especificamente à reação. Além disso, o artigo é apresentado sob a tag react e os desenvolvedores escreveram a reação .
Não é fácil criar componentes que muitos desenvolvedores usarão. Você deve considerar cuidadosamente quais objetos usar se esses objetos fizerem parte da API pública.
Neste artigo, faremos uma breve introdução a algumas das melhores práticas para o desenvolvimento da API como um todo, além de formar dez mandamentos que você pode usar para criar componentes que seus colegas desenvolvedores terão prazer em usar.

O que é uma API?
Uma API - ou interface de programação de aplicativos - é onde dois pedaços de código se encontram. Essa é a superfície de contato entre seu código e o resto do mundo. Chamamos essa superfície de interface. Este é um conjunto específico de ações ou pontos de dados com os quais você pode interagir.
A interface entre a classe e o código que chama essa classe também é uma API. Você pode chamar os métodos da classe para receber dados ou executar as funções incluídas nele.
Seguindo o mesmo princípio, os props que seu componente aceita, essa é sua API . É assim que os desenvolvedores interagem com seu componente.
Algumas práticas recomendadas de design de API
Então, quais regras e considerações se aplicam ao desenvolver uma API? Bem, fizemos uma pequena pesquisa e constatamos que existem muitos recursos excelentes sobre esse assunto. Escolhemos dois - Josh Tauberer - "O que faz uma boa API?" e um artigo de Ron Kurir com o mesmo título - e chegou a essas quatro práticas.
Versões estáveis
Uma das coisas mais importantes a considerar ao criar uma API é mantê-la o mais estável possível. O número de mudanças críticas deve ser mínimo. Se você precisar fazer alterações críticas, escreva guias de atualização detalhados e, se possível, escreva um código mod que automatize esse processo para os desenvolvedores.
Mensagens de erro descritivas
Sempre que ocorrer um erro ao chamar sua API, você deve fazer todo o possível para explicar o que deu errado e como corrigi-lo. Se você censurar o usuário com mensagens como "uso indevido" e não fornecer nenhuma explicação, sua API deixará uma má impressão.
Em vez disso, escreva erros descritivos que ajudam o usuário a corrigir como eles usam sua API.
Minimize surpresas para desenvolvedores
Os desenvolvedores são criaturas frágeis e você não deve assustá-los quando usarem sua API. Em outras palavras, torne sua API o mais intuitiva possível. Você conseguirá isso se seguir as práticas recomendadas e as convenções de nomenclatura existentes.
Além disso, seu código deve sempre ser consistente. Se você usar os nomes lógicos das propriedades com is
ou has
em um local, mas ignorá-los ainda mais, isso confundirá as pessoas.
Minimizar a superfície da API
Sua API também precisa ser minimizada. Muitos recursos são ótimos, mas quanto menor a superfície da sua API (superfície da API), menos desenvolvedores precisarão estudá-la para começar a trabalhar produtivamente com ela. Graças a isso, sua API será percebida como fácil de usar!
Sempre existe uma maneira de controlar o tamanho das suas APIs. Um deles é refatorar a nova API da antiga.
Os dez mandamentos para componentes da Web

Portanto, essas quatro regras de ouro funcionam bem para a API REST e para as antigas partes processuais do Pascal - mas como transferi-las para o mundo moderno do React?
Como dissemos anteriormente, os componentes têm sua própria API. Nós os chamamos de props
e é com a ajuda deles que os dados são transferidos para os componentes. Como estruturamos adereços para não violar nenhuma das regras acima?
Criamos esta lista de dez regras de ouro que são melhor seguidas ao criar seus componentes. Esperamos que eles sejam úteis para você.
1. Documente o uso de componentes
Se a maneira como você deseja usar seu componente não estiver documentada, esse componente será inútil. Bem, quase inútil, você sempre pode olhar para sua implementação, mas poucas pessoas gostam de fazer isso.
Existem várias maneiras de documentar seus componentes, mas recomendamos que você preste atenção a estes três:
Os dois primeiros oferecem um local para você trabalhar no desenvolvimento de seus componentes, e o terceiro permite que você escreva a documentação de forma livre usando o MDX
Não importa o que você escolher, sempre documente a API em si e como e quando seus componentes devem ser usados . A última parte é crítica nas bibliotecas de uso geral - para as pessoas usarem corretamente um botão ou grade de layout em um determinado contexto.
2. Ativar semântica contextual
HTML é uma linguagem para estruturar informações de maneira semântica. Somente aqui, a maioria dos nossos componentes consiste em tags <div />
. Isso faz sentido - componentes universais não podem saber antecipadamente o que serão, talvez <article />
, ou <section />
ou <aside />
- mas essa situação está longe de ser ideal.
Há outra opção: deixe seus componentes aceitarem prop as
e, assim, determine qual elemento DOM será renderizado. Aqui está um exemplo de como implementar isso:
function Grid({ as: Element, ...props }) { return <Element className="grid" {...props} /> } Grid.defaultProps = { as: 'div', };
Renomeamos prop as
à variável Element
e a usamos em nosso JSX. Fornecemos um valor div
padrão comum se não tivermos uma tag HTML mais semântica para passar.
Quando chegar a hora de usar o componente <Grid />
, você pode simplesmente passar a tag correta:
function App() { return ( <Grid as="main"> <MoreContent /> </Grid> ); }
Isso também funciona com os componentes React. Por exemplo, se você deseja que o componente <Button />
renderize o <Link />
do React Router:
<Button as={Link} to="/profile"> Go to Profile </Button>
3. Evite adereços booleanos
Adereços lógicos são uma boa ideia. Eles podem ser usados sem valor, por isso parece muito elegante:
<Button large>BUY NOW!</Button>
Mas, embora pareça bom, as propriedades lógicas permitem apenas duas possibilidades. Ativado ou desativado Visível ou oculto. 1 ou 0.
Sempre que você começa a introduzir propriedades lógicas para itens como tamanho, opções, cores ou qualquer outra coisa que não seja uma opção binária, você tem problemas.
<Button large small primary disabled secondary> ?? </Button>
Em outras palavras, as propriedades lógicas geralmente não se adaptam às mudanças nos requisitos. Em vez disso, para valores que podem se tornar algo diferente de uma seleção binária, é melhor usar valores enumerados, como seqüências de caracteres.
<Button variant="primary" size="large"> </Button>
Isso não significa que propriedades lógicas não possam ser usadas. Você pode! O suporte disabled
, que listei acima, ainda deve ser lógico - porque não há estado intermediário entre ativado e desativado. Apenas deixe as propriedades booleanas apenas para uma escolha verdadeiramente binária.
4. Use props.children
O React possui algumas propriedades especiais que são tratadas de maneira diferente das outras. Uma dessas key
é necessária para rastrear a ordem dos itens da lista. E outro desses objetos especiais são as children
.
Tudo o que você coloca entre a tag de abertura e fechamento do componente é colocado dentro do props.children
. E você deve usar isso o mais rápido possível.
Porque Porque é muito mais fácil do que ter content
prop para conteúdo ou algo parecido que normalmente usa apenas valores simples, como texto.
<TableCell content="Some text" /> // <TableCell>Some text</TableCell>
Existem várias vantagens em usar props.children
. Em primeiro lugar, isso é semelhante ao funcionamento do HTML comum. Em segundo lugar, você pode transferir livremente o que quiser! Em vez de adicionar adereços como leftIcon
e rightIcon
ao seu componente - apenas passe-os como parte do props.children
:
<TableCell> <ImportantIcon /> Some text </TableCell>
Você pode argumentar que seu componente só precisa renderizar texto sem formatação e, em alguns casos, é. Até algum ponto. Usando props.children
, você garante que sua API estará pronta para alterar os requisitos.
5. Deixe o pai se apegar à lógica interna
Às vezes, criamos componentes com muita lógica e estados internos - por exemplo, diagramas de preenchimento automático ou interativo.
Esses componentes geralmente sofrem de APIs excessivas, uma das razões para isso é o grande número de casos de uso diferentes que se acumulam com o desenvolvimento do projeto.
Mas e se pudéssemos fornecer um suporte único e padronizado que permita ao desenvolvedor controlar, responder ou simplesmente alterar o comportamento padrão do componente?
Kent Dodds escreveu um excelente artigo sobre o conceito de redutores de estado. Aqui está um artigo sobre o próprio conceito e também um artigo sobre como implementar isso para ganchos do React .
Em resumo, esse é um padrão de transferência de função de redutor de estado para o seu componente, o que permitirá ao desenvolvedor acessar todas as ações executadas dentro do seu componente. Você pode mudar de estado ou até causar efeitos colaterais. Essa é uma ótima maneira de fornecer um alto nível de personalização, sem adereços .
Aqui está o que pode parecer:
function MyCustomDropdown(props) { const stateReducer = (state, action) => { if (action.type === Dropdown.actions.CLOSE) { buttonRef.current.focus(); } }; return ( <> <Dropdown stateReducer={stateReducer} {...props} /> <Button ref={buttonRef}>Open</Button> </> }
A propósito, você pode criar maneiras mais simples de responder a eventos. O uso do onClose
no exemplo anterior provavelmente tornará o uso do componente mais conveniente. Use o padrão "redutor de estado" quando necessário.
6. Use o operador de propagação para os demais adereços
Cada vez que você cria um novo componente, aplique as reticências aos objetos restantes e envie-as ao elemento para o qual isso faz sentido.
Você não precisa continuar adicionando acessórios ao seu componente, que simplesmente será passado para o componente ou elemento base. Isso tornará sua API mais estável, eliminando a necessidade de muitos erros de versão pequena quando o próximo desenvolvedor precisar de um novo ouvinte de evento ou tag ARIA.
Você pode fazer assim:
function ToolTip({ isVisible, ...rest }) { return isVisible ? <span role="tooltip" {...rest} /> : null; }
Sempre que seu componente passa prop para sua implementação, como um nome de classe ou manipulador onClick
, verifique se outro desenvolvedor pode fazer o mesmo. No caso de uma classe, você pode simplesmente adicionar a classe prop usando a conveniente biblioteca de nomes de classe npm (ou apenas concatenação de cadeias):
import classNames from 'classnames'; function ToolTip(props) { return ( <span {...props} className={classNames('tooltip', props.tooltip)} /> }
No caso de manipuladores de clique e outros retornos de chamada, você pode combiná-los em uma função usando um pequeno utilitário. Aqui está uma maneira de fazer isso:
function combine(...functions) { return (...args) => functions .filter(func => typeof func === 'function') .forEach(func => func(...args)); }
Aqui, criamos uma função que aceita uma lista de funções para combiná-las. Ele retorna um novo retorno de chamada, que chama todos eles por sua vez, com os mesmos argumentos.
Esta função pode ser usada desta maneira:
function ToolTip(props) { const [isVisible, setVisible] = React.useState(false); return ( <span {...props} className={classNames('tooltip', props.className)} onMouseIn={combine(() => setVisible(true), props.onMouseIn)} onMouseOut={combine(() => setVisible(false), props.onMouseOut)} /> ); }
7. Use os valores padrão
Certifique-se de fornecer padrões suficientes (padrões) aos seus acessórios. Assim, você reduzirá o número de adereços obrigatórios. Isso simplificará bastante sua API.
Pegue, por exemplo, o manipulador onClick
. Se o seu código não precisar desse manipulador, use a função vazia (função noop) como o suporte padrão. Dessa forma, você pode chamá-lo em seu código como se sempre fosse passado.
Outro exemplo pode ser a entrada do usuário. Suponha que a sequência de entrada seja uma sequência vazia, a menos que especificado de outra forma. Isso permitirá que você sempre lide com um objeto string, não com algo indefinido ou nulo.
8. Não há necessidade de renomear atributos HTML
O HTML como idioma possui seus próprios props - ou atributos, e ele próprio é uma API para elementos HTML. Então, por que não continuar usando esta API?
Como mencionamos anteriormente, minimizar a superfície da API e sua intuitividade são métodos úteis para melhorar a API de seus componentes. Então, em vez de criar seu próprio suporte screenReaderLabel
, por que não usar apenas um aria-label
existente?
Evite renomear quaisquer atributos HTML existentes para sua própria "facilidade de uso". Você nem substitui a API existente - basta adicionar a sua própria sobre ela. As pessoas ainda podem passar o aria-label
da aria-label
junto com o screenReaderLabel
screenReaderLabel - e qual deve ser o valor final?
Além disso, nunca substitua os atributos HTML em seus componentes. Um ótimo exemplo é o atributo type
do elemento <button />
. Pode ser submit
(padrão), button
ou reset
. No entanto, muitos desenvolvedores redefinem esse suporte para indicar o tipo visual do botão ( primary
, cta
etc.).
Se você usar esse suporte, precisará adicionar uma substituição para o atributo true type
. Isso levará a confusão, dúvida e aborrecimento por parte dos desenvolvedores.
Acredite em mim - cometi esse erro repetidamente - se você o cometer, terá que desembaraçá-lo por um longo tempo.
9. Escreva os tipos de adereços (ou apenas os tipos)
Nenhuma documentação será tão boa quanto a documentação que está dentro do seu código. O React vem com uma ótima maneira de declarar suas APIs usando o pacote prop-types
. Use-o.
Você pode especificar quaisquer requisitos de formato para seus acessórios obrigatórios e opcionais e pode aprimorá- los com comentários do JSDoc .
Se você não especificar um suporte obrigatório ou passar um valor inválido ou inesperado, em tempo de execução, você receberá um aviso no console. Isso ajuda muito durante o desenvolvimento e pode ser removido da produção.
Se você escreve seus aplicativos React no TypeScript ou usa o Flow, obtém a documentação da API como uma função de linguagem. Isso aprimora ainda mais o suporte das ferramentas de desenvolvimento e simplifica o trabalho.
Se você mesmo não usar JavaScript digitado, considere fornecer definições de tipo para os desenvolvedores que o usam. Então será muito mais fácil eles usarem seus componentes.
10. Design para desenvolvedores
Finalmente, a regra mais importante a seguir. Verifique se sua API e o trabalho com seus componentes estão otimizados para desenvolvedores que a usarão.
Uma maneira de simplificar o trabalho de um desenvolvedor é fornecer feedback sobre o uso inadequado. Faça isso com mensagens de erro e também, mas apenas durante o desenvolvimento, com avisos de que existem maneiras mais eficientes de usar seu componente.
Ao escrever erros e avisos, forneça links para sua documentação ou mostre exemplos simples de código. Quanto mais rápido o desenvolvedor entender qual é o problema e como corrigi-lo, mais conveniente será o seu componente para o trabalho.
Incrivelmente, mas, como se viu, a presença de todos esses avisos de erro longos não afeta o tamanho do pacote final. Graças aos milagres de eliminar o código morto, todo esse texto e código de erro podem ser removidos durante a montagem na produção.
Uma das bibliotecas que fornece um feedback incrivelmente bom é o próprio React. Não importa se você esqueceu de especificar a chave para os itens da lista, ou se escreveu o método do ciclo de vida incorretamente, ou se esqueceu de estender a classe base ou chamou o gancho de maneira incerta - em qualquer caso, você receberá grandes e grossas mensagens de erro no console. Por que os desenvolvedores que usam seus componentes esperam menos de você?
Então, crie para seus futuros usuários. Projete para si mesmo a partir do futuro. Projete para os infelizes que terão que manter seu código quando você sair! Design para desenvolvedores.
Total
Podemos aprender muito com a abordagem clássica da API. Seguindo as dicas, truques, regras e mandamentos deste artigo, você pode criar componentes fáceis de usar, fáceis de manter, intuitivos e, se necessário, muito flexíveis.