Escrevemos API para componentes React, parte 6: criamos comunicação entre componentes

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

Vamos falar sobre formulários.


Provavelmente você lê vários artigos sobre gerenciamento de state em formulários, mas esse não é um desses artigos. Em vez disso, quero falar sobre como os formulários e suas APIs funcionam.


etiqueta à esquerda


Há muita coisa acontecendo aqui, dê uma olhada na API


 <Form layout="label-on-left"> <Form.Field label="Name"> <TextInput type="text" placeholder="Enter your name" /> </Form.Field> <Form.Field label="Email"> <TextInput type="email" placeholder="email@domain.com" /> </Form.Field> </Form> 

Vamos examinar cada um dos componentes e analisá-los:


Formulário


Tudo começa com o componente Form , que é o elemento básico do formulário com uma classe anexada. Ele renderizará tudo o que você colocar nele.


 function Form(props) { return <form className="form">{props.children}</form> } render(<Form layout="label-on-left">...</Form>) 

Também aceita layout suporte, o que é útil quando você tem pouco espaço.


etiqueta na parte superior do telefone


 <Form layout="label-on-top">...</Form> 

Isso altera a maneira como os rótulos são alinhados (da direita para a esquerda) e como a margin funciona.


O formulário não controla a largura e a margin seu conteúdo interno. Isso já é uma preocupação para o campo de entrada dentro deste formulário.


Portanto, o componente Form deve relatar informações de layout abaixo.


A maneira mais fácil seria passar o layout usando adereços, mas o conteúdo do formulário é dinâmico (determinado pelo desenvolvedor que o usa), não sabemos exatamente qual será o formulário.


É aqui que a API de contexto nos ajuda.


 /*    */ const LayoutContext = React.createContext() function Form(props) { /*     `Provider`       */ return ( <form className="form"> <LayoutContext.Provider value={{ layout: props.layout }} > {props.children} </LayoutContext.Provider> </form> ) } export default Form export { LayoutContext } 

Agora o campo do formulário pode usar esse contexto e obter o valor do layout


Campo de formulário


O componente FormField (campo de entrada do formulário) adiciona um label a tudo o que você coloca nele (por exemplo, entrada de texto).


 function Field(props) { return ( <div className="form-field"> <label {...props}>{props.label}</label> {props.children} </div> ) } 

Além disso, ele adiciona uma classe para o layout - que vem do contexto que criamos no componente Form .


 /*   layout */ import { LayoutContext } from './form' /*           -     API (Render Prop API)         */ function Field(props) { return ( <LayoutContext.Consumer> {context => ( <div className={`form-field ${context.layout}`}> <label {...props}>{props.label}</label> {props.children} </div> )} </LayoutContext.Consumer> ) } 

React 16.8+ useContext hook facilita a sintaxe


 /*   layout */ import { LayoutContext } from './form' function Field(props) { /*    useContext          */ const context = useContext(LayoutContext) return ( <div className={`form-field ${context.layout}`}> <label {...props}>{props.label}</label> {props.children} </div> ) } 

Se você estiver interessado, aqui está o código css:


 .form-field.label-on-left { max-width: 625px; display: flex; align-items: center; /*    */ } .form-field.label-on-left label { text-align: right; width: 175px; margin-right: 25px; } .form-field.label-on-top { width: 100%; display: block; /*  flex*/ } .form-field.label-on-top label { text-align: left; /*  right */ margin-bottom: 25px; /*  margin-right */ } 

Form.Field?


O último detalhe sobre o qual quero falar é sobre essa estranha sintaxe pontilhada para componentes.


Como o Field (o campo de entrada) é sempre usado com um formulário, faz sentido agrupá-los.


Uma maneira de fazer isso é exportá-lo do mesmo arquivo:


 /* form.js */ import Field from './field' function Form(props) { /* ... */ } export default Form export { Field } 

E agora os usuários podem importá-los juntos:


 import Form, { Field } from 'components/form' render( <Form> <Field>...</Field> </Form> ) 

Podemos fazer uma pequena melhoria anexando Field ao próprio componente do formulário.


 /* form.js */ import Field from './field' function Form(props) { /* ... */ } Form.Field = Field export default Form 

Esse código funciona porque os componentes React são objetos javascript e você pode adicionar chaves adicionais a esses objetos.


Para o usuário, isso significa que, quando ele importa um Form , ele recebe um Field automaticamente.


 import Form from 'components/form' render( <Form> <Form.Field>...</Form.Field> </Form> ) 

Eu realmente gosto dessa API, que torna óbvia a conexão entre Form e Form.Field .


Nota: você deve mover o contexto para outro arquivo para evitar dependência circular.


A combinação de sintaxe com pontos e contexto torna nosso componente Form inteligente, mantendo sua operabilidade para composições (compostas).

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


All Articles