Écriture d'une API pour les composants React, partie 1: ne créez pas d'accessoires conflictuels
Écriture d'une API pour les composants React, partie 2: donner des noms au comportement, pas à l'interaction
Écriture d'une API pour les composants React, partie 3: l'ordre des accessoires est important
Écriture d'une API pour React Components, Partie 4: Méfiez-vous de l'Apropacalypse!
Écriture d'une API pour les composants React, partie 5: il suffit d'utiliser la composition
Nous écrivons API pour les composants React, partie 6: nous créons la communication entre les composants
Parlons des formulaires.
Vous avez probablement lu un tas d'articles sur state
gestion de l' state
dans les formulaires, mais ce n'est pas l'un de ces articles. Au lieu de cela, je veux parler du fonctionnement des formulaires et de leurs API.

Il se passe beaucoup de choses ici, jetez un oeil à l'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>
Examinons chacun des composants et analysons-les:
Tout commence par le composant Form
, qui est l'élément de formulaire de base avec une classe attachée. Il rendra tout ce que vous y mettez.
function Form(props) { return <form className="form">{props.children}</form> } render(<Form layout="label-on-left">...</Form>)
Il accepte également la layout
accessoires, ce qui est utile lorsque vous avez peu d'espace.

<Form layout="label-on-top">...</Form>
Cela change la façon dont les étiquettes sont alignées (de droite à gauche) et le fonctionnement de la margin
.
Le formulaire ne contrôle pas la largeur et la margin
son contenu interne. C'est déjà une préoccupation pour le champ de saisie à l'intérieur de ce formulaire.
Le composant Form
doit donc rapporter les informations de layout
ci-dessous.
Le moyen le plus simple serait de passer la layout
en layout
aide d'accessoires, mais le contenu du formulaire est dynamique (déterminé par le développeur qui utilise ce formulaire), nous ne savons pas exactement ce que sera le formulaire.
C'est là que l'API contextuelle nous aide.
const LayoutContext = React.createContext() function Form(props) { return ( <form className="form"> <LayoutContext.Provider value={{ layout: props.layout }} > {props.children} </LayoutContext.Provider> </form> ) } export default Form export { LayoutContext }
Maintenant, le champ du formulaire peut utiliser ce contexte et obtenir la valeur de layout
Le composant FormField
(champ de saisie de formulaire) ajoute une label
à tout ce que vous y mettez (par exemple, la saisie de texte).
function Field(props) { return ( <div className="form-field"> <label {...props}>{props.label}</label> {props.children} </div> ) }
En plus de cela, il ajoute une classe pour la layout
- qui vient du contexte que nous avons créé dans le composant Form
.
import { LayoutContext } from './form' 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 facilite la syntaxe
import { LayoutContext } from './form' function Field(props) { const context = useContext(LayoutContext) return ( <div className={`form-field ${context.layout}`}> <label {...props}>{props.label}</label> {props.children} </div> ) }
Si vous êtes intéressé, voici le code 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; } .form-field.label-on-top label { text-align: left; margin-bottom: 25px; }
Le dernier détail dont je veux parler est cette étrange syntaxe en pointillés pour les composants.
Étant donné que Field
(le champ de saisie) est toujours utilisé avec un formulaire, il est logique de les regrouper.
Pour ce faire, vous pouvez l'exporter à partir du même fichier:
import Field from './field' function Form(props) { } export default Form export { Field }
Et maintenant, les utilisateurs peuvent les importer ensemble:
import Form, { Field } from 'components/form' render( <Form> <Field>...</Field> </Form> )
Nous pouvons apporter une petite amélioration en attachant Field
au composant même du formulaire.
import Field from './field' function Form(props) { } Form.Field = Field export default Form
Ce code fonctionne car les composants React sont des objets javascript et vous pouvez ajouter des clés supplémentaires à ces objets.
Pour l'utilisateur, cela signifie que lorsqu'il importe un Form
, il reçoit automatiquement un Field
.
import Form from 'components/form' render( <Form> <Form.Field>...</Form.Field> </Form> )
J'aime vraiment cette API, elle rend la connexion entre Form
et Form.Field
évidente.
Remarque: vous devez déplacer le contexte vers un autre fichier pour éviter une dépendance circulaire.
La combinaison de la syntaxe avec les points et le contexte rend notre composant Form
intelligent, tout en conservant son opérabilité pour les compositions (composite).