Escribimos API para componentes React, parte 6: creamos comunicación entre componentes

Escribir una API para componentes React, parte 1: no cree accesorios conflictivos

Escribir una API para React Components, Parte 2: Dar nombres al comportamiento, no a la interacción

Escribir una API para componentes React, parte 3: el orden de los accesorios es importante

Escribir una API para React Components, Parte 4: ¡Cuidado con el Apropacalypse!

Escribir una API para React Components, Parte 5: solo use la composición

Escribimos API para componentes React, parte 6: creamos comunicación entre componentes

Hablemos de formas.


Lo más probable es que leas un montón de artículos sobre state gestión del state en formularios, pero este no es uno de esos artículos. En cambio, quiero hablar sobre cómo funcionan los formularios y sus API.


etiqueta a la izquierda


Están sucediendo muchas cosas aquí, eche un vistazo a la 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> 

Miremos cada uno de los componentes y analicémoslos:


Forma


Todo comienza con el componente Form , que es el elemento de formulario básico con una clase adjunta. Representará todo lo que pones en él.


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

También acepta el layout accesorios, lo que es útil cuando tienes poco espacio.


etiqueta en el teléfono superior


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

Esto cambia la forma en que se alinean las etiquetas (de derecha a izquierda) y cómo funciona el margin .


El formulario no controla el ancho y el margin su contenido interno. Esto ya es una preocupación para el campo de entrada dentro de este formulario.


Entonces, el componente Form debe informar la información de layout continuación.


La forma más fácil sería pasar el layout usando accesorios, pero el contenido del formulario es dinámico (determinado por el desarrollador que usa este formulario), no sabemos exactamente cuál será el formulario.


Aquí es donde la API de contexto nos ayuda.


 /*    */ 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 } 

Ahora el campo de formulario puede usar este contexto y obtener el valor del layout


Campo de formulario


El componente FormField (campo de entrada de formulario) agrega una label a todo lo que ingresa (por ejemplo, entrada de texto).


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

Además de esto, agrega una clase para el layout , que proviene del contexto que creamos en el 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 la sintaxis


 /*   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> ) } 

Si está interesado, aquí está el 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 */ } 

Forma ¿Campo?


El último detalle del que quiero hablar es esta extraña sintaxis punteada para componentes.


Como Field (el campo de entrada) siempre se usa con un formulario, tiene sentido agruparlos.


Una forma de hacerlo es exportarlo desde el mismo archivo:


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

Y ahora los usuarios pueden importarlos juntos:


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

Podemos hacer una pequeña mejora adjuntando Field al mismo componente del formulario.


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

Este código funciona porque los componentes React son objetos javascript, y puede agregar claves adicionales a estos objetos.


Para el usuario, esto significa que cuando importa un Form , recibe un Field automáticamente.


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

Realmente me gusta esta API, hace que la conexión entre Form y Form.Field obvia.


Nota: debe mover el contexto a otro archivo para evitar la dependencia circular.


La combinación de sintaxis con puntos y contexto hace que nuestro componente Form inteligente, al tiempo que mantiene su operatividad para composiciones (compuestas).

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


All Articles