Escrevendo uma API para reagir componentes, parte 5: apenas usar composição

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


<Badge count={12} /> 

Você os viu em várias aplicações, eles mostram o número de objetos como um número.


github-1


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


crachá-2


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


github-2


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


label-2


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


juntos 2


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


juntos 2


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


juntos 2


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


alerta


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?

código


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.


  1. Você não precisa pensar sobre como o text prop é chamado? label ? Estes são apenas children .
  2. 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.
  3. 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 .


 //    const MyContext = React.createContext() //    //    function App() { return ( <MyContext.Provider value="5"> <Counter /> </MyContext.Provider> ) } //    //   function Counter() { return ( <MyContext.Consumer> {value => ( <div className="counter">the count is: {value}</div> )} </MyContext.Consumer> ) } 

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.

Source: https://habr.com/ru/post/pt459416/


All Articles