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>
);
}
}
4 Réponses :
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:
Mot de passe trop court
{this.state.password.length <5 &&
Peut-être consulter https://github.com/jaredpalmer/formik et regardez quelques exemples.
Je reçois cette erreur TypeError: Impossible de lire la propriété 'length' de undefined
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>
);
}
}
le seul, le {this.state.formData.password.length <6 && // affiche une erreur ici doesn ' t afficher quoi que ce soit {this.state.errors.password}
}
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 a> 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.
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>
}
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>
)
}
Il semble que vous deviez remplacer
this.password> 6parthis.state.password.length <6im obtenant
TypeError: Impossible de lire la propriété 'length' de undefined