1
votes

Le moyen le plus simple de valider les formulaires dans React

Je ne sais pas trop comment faire une validation de formulaire dans react.

Je souhaite afficher un message d'erreur sur la page actuelle disant. Cependant, la validation du mot de passe est ignorée et aucune erreur n'apparaît sur la page.

Le mot de passe doit contenir au moins des caractères

Peut-être que je n'utilise pas rendu conditionnel à droite

SignUp.js (extrait à des fins de démonstration)

constructor(props){
 super(props);

 this.state ={
  errors: {},
}

handleSubmit(event) {
  event.preventDefault();

  const email = this.email.value;
  const password = this.password.value;

  if(password.length > 6){
    this.state.errors.password= "Password must be at least 6 characters";
  }
  const creds = {email, password}

  if(creds){
    this.props.signUp(creds);
    this.props.history.push('/');

  }
}

render() {
 return (
  <div className="container">
    <div className="row">
      <div className="col-md-6">
        <h1>Sign Up</h1>
        <form onSubmit={this.handleSubmit}>
          <div className="form-group">
            <label htmlFor="exampleInputEmail1">Email address</label>

            <input
              name="email"
              type="email"          
              className="form-control"
              id="email"
              ref={(input) => this.email = input}
              aria-describedby="emailHelp"
              placeholder="Enter email" />
            <small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
          </div>
          <div className="form-group">
            <label htmlFor="exampleInputPassword1">Password</label>
            {this.password > 6 &&
               //display an error here
              <h2>{this.state.errors.password}</h2>
            }
            <input
              name="password"
              type="password"
              ref={(input) => this.password = input}
              value={this.state.password}
              className="form-control"
              id="password"    
              placeholder="Password" />

          </div>



          <button type="submit" className="btn btn-primary">Submit</button>
        </form>
      </div>

    </div>
  </div>

  );
 }

} 


2 commentaires

Il semble que vous deviez remplacer this.password> 6 par this.state.password.length <6


im obtenant TypeError: Impossible de lire la propriété 'length' de undefined


4 Réponses :


0
votes

Cet exemple n'utilise pas l'état du composant pour gérer les champs Mot de passe et E-mail.

En les ayant comme champs de saisie contrôlés, vous pouvez ensuite les valider en cas de modification et les rendre conditionnellement sous forme de message d'erreur (qui n'a pas besoin d'être maintenu dans l'état)

par exemple. si vous vouliez afficher une erreur, le mot de passe est trop court:

{this.state.password.length <5 &&

Mot de passe trop court

}

Peut-être consulter https://github.com/jaredpalmer/formik et regardez quelques exemples.


1 commentaires

Je reçois cette erreur TypeError: Impossible de lire la propriété 'length' de undefined



2
votes

Vous devez stocker les données du formulaire dans l'état de votre composant. Par exemple, utilisez this.state.email au lieu de this.email . Lorsque les données stockées dans l'état d'un composant sont mises à jour, un rendu est déclenché. Cependant, les rerenders ne sont pas déclenchés pour les mises à jour des variables de classe simples. Vous manipulez également directement l'état lorsque vous définissez les erreurs . À la place, vous devez utiliser la méthode setState docs .

La raison pour laquelle vous ne voyez pas votre erreur affichée sur la page est que votre page ne se rend pas correctement en raison de changements dans le formulaire.

Notez que c'est également une bonne idée d'encapsuler vos variables de données de formulaire dans un objet formData dans l'état pour l'organisation. Cela permet de séparer les données du formulaire du reste de l'état du composant (par exemple, sépare les valeurs du formulaire de votre variable d'erreurs) et permet aux données du formulaire d'être transmises plus facilement, par exemple lors de la soumission du formulaire.

Voici un exemple de la façon dont vous pouvez réorganiser les choses:

handleChange = event => {
    const { formData } = this.state;
    const { name, type, value, checked } = event.target;
    this.setState({
        formData: {
            ...formData,
            [name]: type === "checkbox" ? checked : value,
        }
    })
}

Remarque: Si votre formulaire comporte des entrées de case à cocher, la méthode handleChange affichée ne fonctionnera pas comme souhaité pour ces champs car la propriété cochée d'une entrée de case à cocher doit être utilisée à la place de la propriété valeur . Pour plus de simplicité, je n'ai inclus que le cas sans case à cocher, mais voici une version complète de handleChange:

constructor(props){
 super(props);

 this.state = {
  formData: { // set up default form values
    email: "",
    password: "",
  },
  errors: {},
}

handleChange = event => {
  const { formData } = this.state;

  this.setState({
    formData: {
      ...formData, // leave other values unchanged
      [event.target.name]: event.target.value, // update the changed value
    }
  });
}

handleSubmit(event) {
  event.preventDefault();

  const { formData, errors } = this.state;
  const { email, password } = formData;

  if (password.length < 6) { // changed comparison to _less_ than
    this.setState({ // update errors using setState -- never directly modify a component's state
      errors: {
        ...errors,
        password: "Password must be at least 6 characters",
      }
    });
  }

  const creds = {email, password}

  if (creds.email && creds.password) { // objects are never falsey, so we need to check each field directly
    this.props.signUp(creds);
    this.props.history.push('/');

  }
}

render() {
 return (
  <div className="container">
    <div className="row">
      <div className="col-md-6">
        <h1>Sign Up</h1>
        <form onSubmit={this.handleSubmit}>
          <div className="form-group">
            <label htmlFor="exampleInputEmail1">Email address</label>

            <input
              name="email"
              type="email"          
              className="form-control"
              id="email"
              value={ this.state.formData.email } {/* control component by storing value in state and updating state when the input changes */}
              onChange={ this.handleChange }
              aria-describedby="emailHelp"
              placeholder="Enter email" />
            <small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
          </div>
          <div className="form-group">
            <label htmlFor="exampleInputPassword1">Password</label>
            {this.state.errors.password &&
               //display an error here
              <h2>{this.state.errors.password}</h2>
            }
            <input
              name="password"
              type="password"
              value={ this.state.formData.password }
              onChange={ this.handleChange }
              className="form-control"
              id="password"    
              placeholder="Password" />

          </div>



          <button type="submit" className="btn btn-primary">Submit</button>
        </form>
      </div>

    </div>
  </div>

  );
 }

} 


5 commentaires

le seul, le {this.state.formData.password.length <6 && // affiche une erreur ici

{this.state.errors.password}

} doesn ' t afficher quoi que ce soit


mais il semble qu'il veut se montrer, il semble invisible. Je peux voir le div descendre légèrement plus pour faire de la place pour l'erreur. mais aucune erreur n'apparaît.


@EricThomas peut être un problème CSS, si vous désactivez CSS ou ouvrez les outils de développement de votre navigateur pouvez-vous voir le message? (J'ai également mis à jour cette section, car la vérification de la longueur du mot de passe est une logique en double, il suffirait de vérifier s'il y a une erreur présente pour le mot de passe)


@HenryWoody Question: Je ne comprenais pas pourquoi le if (creds) {...} fonctionnerait comme souhaité. Dans ce JSBin, cela fonctionne même lorsque email et password sont vides: jsbin.com/zelipad/edit?js,console . Précisez s'il vous plaît. Merci!


@merci_in_advance vous avez raison. Le code de cette réponse a commencé avec le code de la question et je n'ai édité que les parties qui ont été spécifiquement posées. Cependant, comme vous le faites remarquer, cette ligne if (creds) est fondamentalement inutile puisque même les objets vides sont véridiques dans JS. Merci pour le commentaire, je vais faire quelques modifications maintenant.



0
votes

Je pense que votre code pour afficher l'erreur montre l'état d'utilisation

if(password.length > 6){
this.setState({ errors: { password: "Password must be at least 6 characters"} 

})
  } else {
this.setState({errors: {}})
}

Et dans le formulaire d'envoi, vous devez mettre à jour votre état

{this.state.errors.password &&
           //display an error here
          <h2>{this.state.errors.password}</h2>
        }


0 commentaires

0
votes

J'ai créé un hook personnalisé pour une validation facile du formulaire. Je pense que ça va te rendre la vie beaucoup plus facile. vous pouvez tirer parti de vos connaissances en matière de validation html.

Github: https://github.com/bluebill1049/react-hook-form a>

Site Web: http://react-hook-form.now.sh

import React from 'react'
import useForm from 'react-hook-form'

function App() {
  const { register, handleSubmit, errors } = useForm() // initialise the hook
  const onSubmit = (data) => { console.log(data) } // callback when validation pass

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="firstname" ref={register} /> {/* register an input */}

      <input name="lastname" ref={register({ required: true })} /> {/* apply required validation */}
      {errors.lastname && 'Last name is required.'} {/* error message */}

      <input name="age" ref={register({ pattern: /\d+/ })} /> {/* apply a Refex validation */}
      {errors.age && 'Please enter number for age.'} {/* error message */}

      <input type="submit" />
    </form>
  )
}


0 commentaires