Escrevendo uma API para componentes React, parte 1: não crie objetos conflitantes
Escrevendo uma API para componentes de reação, parte 2: dê nomes ao comportamento, não à interação
Escrevendo uma API para componentes React, parte 3: a ordem dos adereços é importante
Escrevendo uma API para reagir componentes, parte 4: Cuidado com o Apropacalypse!
Escrevendo uma API para reagir componentes, parte 5: apenas usar composição
Escrevemos API para componentes React, parte 6: criamos comunicação entre componentes
Temos um componente de ícone:

<Badge count={12} />
Você os viu em várias aplicações, eles mostram o número de objetos como um número.

O emblema do cosmos (ícone) possui várias cores para cada contexto específico (informações, perigo, etc.)

<Badge count={12} appearance="information" /> <Badge count={12} appearance="success" /> <Badge count={12} appearance="default" /> <Badge count={12} appearance="warning" /> <Badge count={12} appearance="danger" />
Essa interface do usuário tem outro componente semelhante - Label
.

Ele também possui várias cores para cada contexto:

<Label text="private" appearance="information" /> <Label text="private" appearance="success" /> <Label text="private" appearance="default" /> <Label text="private" appearance="warning" /> <Label text="private" appearance="danger" />
Observe esses dois componentes e diga uma coisa boa e outra ruim sobre a API (sobre os adereços)

<Badge count={12} appearance="information" /> <Label text="private" appearance="information" />
Que bom
Ambos os componentes têm o mesmo suporte para a aparência: appearance
, isso é ótimo. Além disso, eles têm as mesmas opções para esse suporte! Se você sabe como usar a appearance
no Badge
, já sabe como usar a appearance
no Label
Lute por adereços consistentes entre os componentes
Dica 2 de escrever uma API para componentes de reação, parte 2: dê nomes ao comportamento, não à interação
O que é ruim
A maneira como eles interpretam seus significados é diferente. Ambos têm sua própria opção.
Contar, count
, faz sentido dentro da estrutura do componente Badge
, mas, levando em consideração todo o restante dos componentes, esta é uma API adicional que sua equipe e usuários (desenvolvedores) precisarão lembrar.
Vamos melhorar essa API
Para ser consistente, chamarei esse content
suporte, esse é o nome mais comum que eu poderia criar - mais geral do que apenas rótulo, texto ou valor.

<Badge content="12" appearance="information" /> <Label content="private" appearance="information" />
Perdemos alguns detalhes, mas obtivemos muita consistência. Ainda podemos definir o tipo de valor com prop-types , então acho que esse é um bom compromisso.
Mas espere, no React já existe um suporte de content
multiuso, chamado children
- uma criança.
Não reinvente props.children.
Se você definiu adereços que aceitam dados arbitrários que não são baseados em uma estrutura de dados, provavelmente é melhor usar a composição - Brent Jackson
Aqui está a dica deste artigo - Ao escolher entre uma composição e adereços, escolha uma composição .
Vamos refatorar esta API com children
, filhos:

<Badge appearance="information">12 </Badge> <Label appearance="information">Private </Label>
Parece ótimo.
Bônus: quando você usa children
vez de prop, o desenvolvedor que usa esse componente obtém mais flexibilidade sem precisar alterar o componente.
Por exemplo, aqui
, quero adicionar um ícone na frente do texto.

Usando children
posso adicionar um ícone a essa
sem retornar a este componente ou alterá-lo.
// - <Alert type="warning" icon="warning" text="This is an important message!" /> // <Alert type="warning"> <Icon name="warning" /> This is an important message! </Alert>
Por coincidência, quando escrevi este texto, vi um tweet de Brad Frost :
Ei, reaja amigos, preciso de uma ajudinha. Eu continuo executando esse padrão em que determinados componentes (especialmente listas) podem ser divididos em componentes menores ou controlados passando um objeto. Qual opção é melhor?

Parece familiar?
Primeiro de tudo, não vamos usar o text
prop e, em vez disso, usar os children
.
// : <Breadcrumb text="Home" href="/child" /> // : <Breadcrumb href="/child">Home</Breadcrumb>
Agora que descobrimos isso, vamos falar sobre essas duas opções de API.
Como não é difícil adivinhar, eu gosto do primeiro.
- Você não precisa pensar sobre como o
text
prop é chamado? label
? Estes são apenas children
. - Você pode adicionar seu
className
ou target
a ele, se necessário. Para a segunda opção, você precisa se certificar de que suporta essas propriedades ou simplesmente as passa para o elemento base. - Isso permite agrupar o filho em um contexto ou em um componente de nível superior.
Exceção à regra:
E se Brad quiser impedir que o desenvolvedor faça as configurações que eu mencionei acima? Então, dar ao desenvolvedor mais flexibilidade, no caso dele, seria um erro!
Aqui está a minha resposta para Brad .
Mais exemplos
Aqui estão mais alguns exemplos de como essa dica pode melhorar seu código, meu último favorito.
Os formulários são um ótimo exemplo de uso, queremos controlar o layout do formulário, exibir erros etc. Mas, ao mesmo tempo, não queremos perder oportunidades de expansão.
// #1 <FormTextInput type="text" label="Name" id="name-input" /> // id, // label input? // #2 <FormField> <Label>Field label</Label> <TextInput id="name-input" type="text" placeholder="What's your name?" /> </FormField> // #3 <FormField label="Field label"> <TextInput id="name-input" type="text" placeholder="What's your name?" /> </FormField>
O último exemplo é particularmente interessante.
Às vezes, você precisa de um componente que será usado em situações muito diferentes. Não é fácil criar um componente flexível e ainda ter uma API simples.
É aqui que a inversão de controle chega ao resgate - deixe o usuário do componente decidir o que renderizar. No mundo React, esse padrão é chamado de padrão de suporte de renderização .
O componente prop de renderização pega uma função que retorna um elemento React e o chama em vez de implementar sua própria renderização.
da documentação do React Render-props
Um dos exemplos mais populares de adereços de renderização é a API de contexto oficial.
No exemplo a seguir, o componente App
controla os dados, mas não controla sua renderização; ele passa esse controle para o componente Counter
.
Você notou algo interessante nesta API do Consumer
?
Em vez de criar uma nova API, ele usa children
para aceitar uma função que diz a ele como renderizar!
// <Consumer render={value => ( <div className="counter">the count is: {value}</div> )} /> // <Consumer> {value => ( <div className="counter">the count is: {value}</div> )} </Consumer>
Volte para o seu código e encontre o componente que aceita adereços quando ele pode usar children
facilmente.