Fermer

octobre 28, 2020

Travailler avec des formulaires dans React


Presque toutes les applications doivent accepter l'entrée de l'utilisateur à un moment donné, et ceci est généralement réalisé avec le formulaire HTML vénérable et sa collection de contrôles d'entrée. Si vous avez récemment commencé à apprendre React, vous êtes probablement arrivé au point où vous vous demandez maintenant: «Comment puis-je travailler avec les formulaires?»

Cet article vous expliquera les bases de l'utilisation des formulaires dans React pour permettre aux utilisateurs d'ajouter ou de modifier des informations. Nous allons examiner deux façons différentes de travailler avec les contrôles d'entrée et les avantages et les inconvénients de chacun. Nous examinerons également comment gérer la validation et certaines bibliothèques tierces pour des cas d'utilisation plus avancés.

Entrées non contrôlées

La manière la plus élémentaire de travailler avec les formulaires dans React est d'utiliser ce à quoi on fait référence comme entrées de formulaire «non contrôlées». Cela signifie que React ne suit pas l’état de l’entrée. Les éléments d'entrée HTML gardent naturellement une trace de leur propre état dans le cadre du DOM, et donc lorsque le formulaire est soumis, nous devons lire les valeurs des éléments DOM eux-mêmes.

Pour ce faire, React nous permet de créer un «Ref» (référence) à associer à un élément, donnant accès au nœud DOM sous-jacent. Voyons comment faire ceci:

 class   SimpleForm   extend   React .  Component   {
   constructor  ( props  )   {
     super  ( props ) ; 
    
     this .  nameEl   =   React . [19659025] createRef  () ; 
     this .  handleSubmit   =   this .  handleSubmit .  bind  ( this ) ; 
  } 

   handleSubmit  ( e )   {
    e .  preventDefault  () ; 
     alert  ( this .  nameEl .  current [19659012].  value ) ; 
  } 

   render  ()   {
     return   (
       < form   onSubmit  =  { this .  handleSubmit }  > 
         < label > [19659081]Nom:
           < input   type  =  " text "    ref  =  { this  .  nameEl }    /> 
         </  label > 
         < input   type  =  "  soumettre  "   nom  = "  Soumettre  "   /> 
       </  form > 
    ) 
  } 
} 

Comme vous pouvez le voir ci-dessus, pour un composant basé sur une classe, vous initialisez une nouvelle référence dans le constructeur en appelant React.createRef en l'attribuant à une propriété d'instance afin qu'elle soit disponible pendant toute la durée de vie du composant.

Afin d'associer la référence à une entrée, elle est passée à l'élément en tant que propriété spéciale réf attribut. Une fois cela fait, le nœud DOM sous-jacent de l'entrée est accessible via this.nameEl.current .

Voyons à quoi cela ressemble dans un composant fonctionnel:

 function   SimpleForm   ( props )   {
   const  nameEl  =   React .  useRef  ( null  ]) ; 

   const   handleSubmit   =   e   =>   {
    e .  preventDefault  () ; 
     alert  ( nameEl .  current .  value [19659012]) ; 
  } ; 

   return   (
      < form   onSubmit  =  { handleSubmit  }  > 
        < label >  Nom:
          < input   type  =  " text "    ref  =  { nameEl  }    /> 
        </  étiquette > 
        < input   type  =  " submit "    name  =  " Submit  "   /> 
      </  form > 
   ) ; 
} 

Il n'y a pas beaucoup de différence ici, à part remplacer createRef par useRef hook.

Exemple: formulaire de connexion

 fonction   LoginForm   ( props )   {
   const  nameEl  =   React .  useRef  ( null ) ; 
   const  passwordEl  =   React  ].  useRef  ( null ) ; 
   const  RememberMeEl  =   React .  useRef  (  null ) ; 

   const   handleSubmit   =   e   =>   {
    e .  preventDefault  () ; 

     const  data  =   {
      nom d'utilisateur :  nameEl .  current .  value 
      password :  passwordEl .  current .  value 
      RememberMe :  RememberMeEl .  current .  checked 
    } 

    
    
  } ; 

   return   ([19659147] < formulaire   onSubmit  =  { handleSubmit }  > 
        < input   type  =  " text "    placeholder  =  " username  "   réf  =  { nameEl }    /> 
        < input   type  =  " password "    placeholder  =  " password  "   ref  =  { passwordEl }    /> 
        < étiquette > 
          < input   type  =  " checkbox "    ref  =  { RememberMeEl  }    /> 
         Souviens-toi de moi
        </  étiquette > 
        < button   type  =  " submit "    className  =  " myButton  " >  Bouton de connexion  </  > 
      </  form > 
   ) ; 
} 

View on CodePen

Alors que les entrées non contrôlées fonctionnent bien pour les formulaires simples et rapides , ils présentent certains inconvénients. Comme vous l'avez peut-être remarqué dans le code ci-dessus, nous devons lire la valeur de l'élément d'entrée chaque fois que nous le voulons. Cela signifie que nous ne pouvons pas fournir une validation instantanée sur le champ lorsque l'utilisateur tape, ni faire des choses comme appliquer un format d'entrée personnalisé, afficher ou masquer sous condition des éléments de formulaire, ou désactiver / activer le bouton d'envoi.

Heureusement, il y a une manière plus sophistiquée de gérer les entrées dans React.

Entrées contrôlées

Une entrée est dite «contrôlée» lorsque React est responsable du maintien et de la définition de son état. L'état est synchronisé avec la valeur de l'entrée, ce qui signifie que la modification de l'entrée mettra à jour l'état et la mise à jour de l'état changera l'entrée.

Voyons à quoi cela ressemble avec un exemple:

 class   ControlledInput   prolonge   React .  Component   {
   constructor  ( props )   {
     super  ( props ) ; 
     this .  state   =   { name :   ''  } [19659012]; 
     this .  handleInput   =   this .  handleInput .  bind  ( this ) ; 
  } 

   handleInput  ( event )   {
     this .  setState  ( { ]
      name :  event .  target .  value 
    } ) ; 
  } 

   render  ([19659012])   {
     return   (
       < input   type  =  " text "    value  =  { this .  state .  name }    onChange  =  { this .  handleInput }    /> 
    ) ; 
  } 
} 

Comme vous pouvez le voir, nous mettons en place un genre du flux de données circulaire: état en valeur d'entrée, lors du changement d'événement en état, et inversement. Cette boucle nous permet beaucoup de contrôle sur l'entrée, car nous pouvons réagir aux changements de valeur à la volée. Pour cette raison, les entrées contrôlées ne souffrent pas des limitations des entrées non contrôlées, ouvrant les possibilités suivantes:

  • validation d'entrée instantanée : nous pouvons donner à l'utilisateur un retour instantané sans avoir à attendre qu'il soumette le formulaire (par exemple, si leur mot de passe n'est pas assez complexe)
  • formatage d'entrée instantané : nous pouvons ajouter des séparateurs appropriés aux entrées de devises, ou regrouper les numéros de téléphone à la volée
  • désactiver conditionnellement la soumission de formulaire : nous pouvons activer le bouton d'envoi une fois que certains critères sont remplis (par exemple, l'utilisateur a consenti aux termes et conditions)
  • générer dynamiquement de nouvelles entrées : nous pouvons ajouter des entrées supplémentaires à un formulaire en fonction de l'entrée précédente de l'utilisateur (par exemple en ajoutant des détails sur personnes supplémentaires sur une réservation d'hôtel)

Validation

Comme je l'ai mentionné plus haut, la boucle de mise à jour continue des composants contrôlés permet d'effectuer une validation continue des entrées au fur et à mesure que l'utilisateur tape. Un gestionnaire attaché à l'événement onChange d'une entrée sera déclenché à chaque frappe, vous permettant de valider ou de formater instantanément la valeur.

Exemple: validation de carte de crédit

Jetons un coup d'œil à un réel- exemple de mot de vérification d'un numéro de carte de crédit lorsque l'utilisateur le saisit dans un formulaire de paiement.

L'exemple utilise une bibliothèque appelée credit-card-type pour déterminer l'émetteur de la carte (comme Amex, Visa, ou Mastercard) que l'utilisateur tape. Le composant utilise ensuite ces informations pour afficher une image du logo de l'émetteur à côté de l'entrée:

 import  creditCardType  from    "credit-card-type" ; 

 function [19659113] CreditCardForm   ( accessoires )   {
   const   [ cardNumber  setCardNumber ]   =   React .  useState  ( "" ) ; 
   const   [ cardTypeImage  setCardTypeImage ]   =   React .  useState  (
     "card-logo-unknown.svg" 
  ) ; 

   const   handleCardNumber   =   ( e )   =>   {
    e .  preventDefault  () ; 

     const  value  =  e .  target . [19659021] value ; 
     setCardNumber  ( value ) ; 

     let  suggestion ; 

     if   ( valeur .  longueur  >   0 )   {
      suggestion  =   creditCardType  ( e .  target .  value )  [ 0 ] [19659012]; 
    } 

     const  cardType  =  suggestion ?  suggestion .  type  :   "unknown" [19659012]; 

     let  imageUrl ; 

     switch   ( cardType )   {
       case   "visa" : 
        imageUrl  =   "card-logo-visa.svg" ; 
         break ; 
       case   "mastercard" : 
        imageUrl  =   "card-logo-mastercard.svg" ; 
         break ; 
       affaire   "american-express" : 
        imageUrl  =   "card-logo-amex.svg" ; 
         break ; 
       default : 
        imageUrl  =   "card-logo-unknown.svg" ; 
    } 

     setCardTypeImage  ( imageUrl ) ; 
  } [19659012]; 

   retour   (
     < formulaire > 
       < div   className  =  " card-number "  > 
         < input 
           type [19659084] =  " texte "  
           placeholder  =  " numéro de carte "  
           valeur  =  { cardNumber }  
           onChange  =  { handleCardNumber } 
         /> 
         < img [19659071] src  =  { cardTypeImage }    alt  =  " logo de la carte "    /> 
       </  div > 
       < button   type  =  " submit "    className  =  " myButton  " > 
        S'identifier
       </  bouton > 
     </  form >  
  ) ; 
} 

Le gestionnaire d'entrée onChange appelle le creditCardType () avec la valeur actuelle. Cela renvoie un tableau de correspondances (ou un tableau vide) qui peut être utilisé pour déterminer quelle image afficher. L'URL de l'image est alors définie sur une variable d'état à rendre dans le formulaire.

Vous pouvez utiliser certains des nombres de ici pour tester l'entrée. [19659553] Bibliothèques de formulaires

Comme vous l'avez peut-être remarqué, il y a une certaine quantité de code passe-partout lorsque vous travaillez avec des formulaires, en particulier avoir à câbler les entrées avec leurs valeurs d'état et leurs gestionnaires. Comme vous vous en doutez, il existe une variété de bibliothèques tierces pour vous aider à vous débarrasser de la difficulté de traiter des formulaires plus volumineux et plus complexes.

Pour vous donner une idée de ce à quoi ressemble l'utilisation d'une bibliothèque de formulaires, prenons un rapide coup d'oeil à celui appelé Fresh . Le but de cette bibliothèque est de couvrir 90% de vos cas d'utilisation courants avec une API simple et facile à utiliser. Voici un exemple de formulaire de modification de profil que vous pourriez trouver dans une application Web:

 import   {  Form   Field  }   from   "@ leveluptuts / fresh "; 

 const  securityQuestions  =   [
  " Quel est le nom de jeune fille de votre mère? "
  " Quel était le nom de votre premier pet? "
  " Quel était le nom de votre première école? "
] ; 

 const   handleSubmit   =   ( data [19659012])   =>   console .  log  ( data ) ; 

 function   UserProfileForm   ()   {
   return   (
     < Form    formId  =  " user-profile "    onSubmit  =  { handleSubmit }  > 
       < Champ    obligatoire >  Prénom  </  Champ  > 
       < Champ    obligatoire >  Nom de famille  </  Champ  > 
       < Champ    obligatoire   type  =  " email "  > 
        Email
       </  Champ  > 

       < Champ    obligatoire   type  =  " select "    options  =  {  securityQuestions }  > 
        Question de sécurité
       </  Champ  > 
       < Champ    obligatoire >  Réponse de sécurité  </  Champ  > 

       < Champ    type  =  " textarea "  >  Bio  </  Champ  > 
     </  Form  >  
  ) ; 
} 

Fresh fournit des composants personnalisés à fabriquer créer des formulaires très simple. Le composant Field se charge de câbler la liaison des données sur les entrées de formulaire, en convertissant l'étiquette que vous fournissez en un nom de propriété en cas de chameau pour la valeur de l'entrée. (Par exemple, "Last Name" devient lastName dans l'état du formulaire.)

Le composant Form encapsule tous les champs et prend un rappel onSubmit qui reçoit les données du formulaire en tant qu'objet. Voici un exemple de la sortie du formulaire:

 {
  firstName :   "Bill" 
  lastName :   "Gates" 
  courriel :   "billg@microsoft.com" 
  securityQuestion :   "Quel était le nom de votre premier animal de compagnie?" 
  securityAnswer :   "Fluffy" 
  bio :   "Bill Gates est un technologue, un chef d'entreprise et un philanthrope. Il a grandi à Seattle, Washington, avec une famille incroyable et solidaire qui a encouragé son intérêt pour les ordinateurs à un âge précoce." 
 } 

Comme vous pouvez le voir, des bibliothèques comme celle-ci peuvent vraiment accélérer le travail avec les formulaires et rendre vos composants beaucoup moins verbeux. Pour autre chose qu'un petit formulaire basique, je vous recommande d'en choisir un qui correspond à vos besoins, car il vous fera gagner du temps à long terme.

Conclusion

Vous devriez maintenant avoir une solide compréhension de la façon dont les entrées peuvent être utilisées dans React. Vous devez connaître la différence entre les entrées contrôlées et non contrôlées, ainsi que les avantages et les inconvénients de chacune, sachant que la boucle de mise à jour étroite d'une entrée contrôlée vous permet de nombreuses options de formatage et de validation des valeurs à la volée. Enfin, vous devez savoir qu'il existe des bibliothèques de formulaires disponibles qui vous évitent d'avoir à ajouter beaucoup de code standard répétitif et détaillé à vos formulaires React, ce qui vous aidera à être un développeur plus productif.




Source link