Reactjs - 表单输入验证

Hul*_*991 34 javascript forms validation node.js reactjs

我的联系页面表格如下,

<form name="contactform" onSubmit={this.contactSubmit.bind(this)}>
  <div className="col-md-6">
    <fieldset>
      <input ref="name" type="text" size="30" placeholder="Name"/>
      <br/>
      <input refs="email" type="text" size="30" placeholder="Email"/>
      <br/>
      <input refs="phone" type="text" size="30" placeholder="Phone"/>
      <br/>
      <input refs="address" type="text" size="30" placeholder="Address"/>
      <br/>
    </fieldset>
  </div>
  <div className="col-md-6">
    <fieldset>
      <textarea refs="message" cols="40" rows="20"
                className="comments" placeholder="Message"/>
    </fieldset>
  </div>
  <div className="col-md-12">
    <fieldset>
      <button className="btn btn-lg pro" id="submit"
              value="Submit">Send Message</button>
    </fieldset>
  </div>
</form>
Run Code Online (Sandbox Code Playgroud)

需要为所有字段添加验证.任何人都可以帮我添加这种反应形式的验证吗?

Bok*_*oky 66

你应该避免使用refs,你可以用onChange函数来做.

在每次更改时,更新已更改字段的状态.

然后,您可以轻松检查该字段是否为空或者您想要的其他内容.

您可以执行以下操作:

class Test extends React.Component {
    constructor(props){
       super(props);

       this.state = {
           fields: {},
           errors: {}
       }
    }

    handleValidation(){
        let fields = this.state.fields;
        let errors = {};
        let formIsValid = true;

        //Name
        if(!fields["name"]){
           formIsValid = false;
           errors["name"] = "Cannot be empty";
        }

        if(typeof fields["name"] !== "undefined"){
           if(!fields["name"].match(/^[a-zA-Z]+$/)){
              formIsValid = false;
              errors["name"] = "Only letters";
           }        
        }

        //Email
        if(!fields["email"]){
           formIsValid = false;
           errors["email"] = "Cannot be empty";
        }

        if(typeof fields["email"] !== "undefined"){
           let lastAtPos = fields["email"].lastIndexOf('@');
           let lastDotPos = fields["email"].lastIndexOf('.');

           if (!(lastAtPos < lastDotPos && lastAtPos > 0 && fields["email"].indexOf('@@') == -1 && lastDotPos > 2 && (fields["email"].length - lastDotPos) > 2)) {
              formIsValid = false;
              errors["email"] = "Email is not valid";
            }
       }  

       this.setState({errors: errors});
       return formIsValid;
   }

   contactSubmit(e){
        e.preventDefault();

        if(this.handleValidation()){
           alert("Form submitted");
        }else{
           alert("Form has errors.")
        }

    }

    handleChange(field, e){         
        let fields = this.state.fields;
        fields[field] = e.target.value;        
        this.setState({fields});
    }

    render(){
        return (
            <div>           
               <form name="contactform" className="contactform" onSubmit= {this.contactSubmit.bind(this)}>
                    <div className="col-md-6">
                      <fieldset>
                           <input ref="name" type="text" size="30" placeholder="Name" onChange={this.handleChange.bind(this, "name")} value={this.state.fields["name"]}/>
                           <span style={{color: "red"}}>{this.state.errors["name"]}</span>
                          <br/>
                         <input refs="email" type="text" size="30" placeholder="Email" onChange={this.handleChange.bind(this, "email")} value={this.state.fields["email"]}/>
                         <span style={{color: "red"}}>{this.state.errors["email"]}</span>
                         <br/>
                         <input refs="phone" type="text" size="30" placeholder="Phone" onChange={this.handleChange.bind(this, "phone")} value={this.state.fields["phone"]}/>
                         <br/>
                         <input refs="address" type="text" size="30" placeholder="Address" onChange={this.handleChange.bind(this, "address")} value={this.state.fields["address"]}/>
                         <br/>
                     </fieldset>
                  </div>

              </form>
            </div>
      )
    }
}

React.render(<Test />, document.getElementById('container'));
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我只对电子邮件和名称进行了验证,但您知道如何进行验证.其余的你可以自己做.

也许有更好的方法,但你会得到这个想法.

这是小提琴.

希望这可以帮助.

  • 不错的选择,但为什么要避免“ref”?任何原因,对于您调用函数的每个输入也是如此吗?是否有任何选项可以通过单击表单提交来获取全部值 (5认同)
  • 很好的解决方案,但有一个错误:组件正在更改要控制的文本类型的不受控制的输入。输入元素不应从不受控制切换到受控制(反之亦然)。在组件的生命周期内决定使用受控或非受控输入元件。 (4认同)

Yas*_*mat 6

试试这个,例如,下面输入标签中的 required 属性将确保 name 字段不应该被提交为空。

<input type="text" placeholder="Your Name" required />
Run Code Online (Sandbox Code Playgroud)

  • 我不知道为什么还没人对此投赞成票。它使用简单明了的内置 html 功能来完成 OP 的要求。如果除了检查必填字段是否已填写之外还有更多需要验证的内容,那么另一个答案似乎是合适的,但在这种情况下,一个简单的“required”道具正是我们所需要的。 (2认同)
  • @Gel 如果输入标签包含在表单元素内,则将考虑表单行为的限制。对于禁用逻辑,我为您提供了一个简单的代码 https://codesandbox.io/s/simple-form-in-react-026bel (2认同)

San*_*Ali 6

假设你了解react useState Hook,如果你的表单很简单,你可以使用state变量来保存每个输入字段的值。然后在每个输入字段上添加onChange处理函数,该函数将更新状态变量。最后,您可以检查状态变量中存储的值,以确保所有输入字段都有一些值。这是一个简单的例子。

import { useState } from "react";

export default function App() {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const onChangeHandler = (fieldName, value)=>{
    if(fieldName === "name"){
      setName(value);
    }
    else if(fieldName==="email"){
      setEmail(value);
    }
  }
  const onSubmitHandler = (e)=>{
    e.preventDefault();
    if(name.trim()==="" || email.trim() ==""){
      alert("required both field");
    }
    else{
      alert(name+" " +email);
      setName("");
      setEmail("");
    }
  }
  return (
    <div className="App">
      <form onSubmit={(e)=>{onSubmitHandler(e)}}>
        <input type="text" value={name} onChange={(e)=>{ onChangeHandler("name",e.target.value)}} /> <br/>
         <input type="email"  value={email} onChange={(e)=>{ onChangeHandler("email",e.target.value)}} /> <br/>
         <input type="submit" value="Submit" />
        </form>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您有复杂的表单,则很难将每个值保留在状态变量中,然后对每个字段使用验证。对于复杂的表单,建议使用react-hook-formFormik,它们会为你做所有事情,你可以使用Yup验证包,它也受支持,Formik它允许你添加不仅仅是简单的验证。


tan*_*y_k 5

我已经采用了你的代码并使用库反应形式与约束进行了调整:https://codepen.io/tkrotoff/pen/LLraZp

const {
  FormWithConstraints,
  FieldFeedbacks,
  FieldFeedback
} = ReactFormWithConstraints;

class Form extends React.Component {
  handleChange = e => {
    this.form.validateFields(e.target);
  }

  contactSubmit = e => {
    e.preventDefault();

    this.form.validateFields();

    if (!this.form.isValid()) {
      console.log('form is invalid: do not submit');
    } else {
      console.log('form is valid: submit');
    }
  }

  render() {
    return (
      <FormWithConstraints
        ref={form => this.form = form}
        onSubmit={this.contactSubmit}
        noValidate>

        <div className="col-md-6">
          <input name="name" size="30" placeholder="Name"
                 required onChange={this.handleChange}
                 className="form-control" />
          <FieldFeedbacks for="name">
            <FieldFeedback when="*" />
          </FieldFeedbacks>

          <input type="email" name="email" size="30" placeholder="Email"
                 required onChange={this.handleChange}
                 className="form-control" />
          <FieldFeedbacks for="email">
            <FieldFeedback when="*" />
          </FieldFeedbacks>

          <input name="phone" size="30" placeholder="Phone"
                 required onChange={this.handleChange}
                 className="form-control" />
          <FieldFeedbacks for="phone">
            <FieldFeedback when="*" />
          </FieldFeedbacks>

          <input name="address" size="30" placeholder="Address"
                 required onChange={this.handleChange}
                 className="form-control" />
          <FieldFeedbacks for="address">
            <FieldFeedback when="*" />
          </FieldFeedbacks>
        </div>

        <div className="col-md-6">
          <textarea name="comments" cols="40" rows="20" placeholder="Message"
                    required minLength={5} maxLength={50}
                    onChange={this.handleChange}
                    className="form-control" />
          <FieldFeedbacks for="comments">
            <FieldFeedback when="*" />
          </FieldFeedbacks>
        </div>

        <div className="col-md-12">
          <button className="btn btn-lg btn-primary">Send Message</button>
        </div>
      </FormWithConstraints>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

截图:

表格验证截图

这是一个快速的黑客攻击.要获得正确的演示,请查看 https://github.com/tkrotoff/react-form-with-constraints#examples


小智 5

import React from 'react';
import {sendFormData} from '../services/';

class Signup extends React.Component{
  constructor(props){
    super(props);
     this.state = {
       isDisabled:true
     }                                                                                                 
     this.submitForm = this.submitForm.bind(this);
  }
  validateEmail(email){
   const pattern = /[a-zA-Z0-9]+[\.]?([a-zA-Z0-9]+)?[\@][a-z]{3,9}[\.][a-z]{2,5}/g;
   const result = pattern.test(email);
   if(result===true){
     this.setState({
       emailError:false,
       email:email
     })
   } else{
     this.setState({
       emailError:true
     })
   }
 }
 handleChange(e){
  const target = e.target;
  const value = target.type === 'checkbox' ? target.checked : target.value;
  const name = target.name;
  this.setState({
    [name]: value
  });
  if(e.target.name==='firstname'){
    if(e.target.value==='' || e.target.value===null ){
      this.setState({
        firstnameError:true
      })
    } else {
      this.setState({
        firstnameError:false,     
        firstName:e.target.value
      })
    }
  }
  if(e.target.name==='lastname'){
    if(e.target.value==='' || e.target.value===null){
      this.setState({
        lastnameError:true
      })
    } else {
      this.setState({
        lastnameError:false,
        lastName:e.target.value
      })
    }
  }
  if(e.target.name==='email'){
   this.validateEmail(e.target.value);
  }
  if(e.target.name==='password'){
    if(e.target.value==='' || e.target.value===null){
      this.setState({
        passwordError:true
      })
    } else {
      this.setState({
        passwordError:false,
        password:e.target.value
      })
    }
 }
 if(this.state.firstnameError===false && this.state.lastnameError===false && 
  this.state.emailError===false && this.state.passwordError===false){
    this.setState({
      isDisabled:false
    })
 }
}
submitForm(e){
  e.preventDefault();
  const data = {
   firstName: this.state.firstName,
   lastName: this.state.lastName,
   email: this.state.email,
   password: this.state.password
  }
  sendFormData(data).then(res=>{
    if(res.status===200){
      alert(res.data);
      this.props.history.push('/');
    }else{

    } 
  });
 }
render(){
return(
  <div className="container">
    <div className="card card-login mx-auto mt-5">
      <div className="card-header">Register here</div>
        <div className="card-body">
            <form id="signup-form">
              <div className="form-group">
                <div className="form-label-group">
                  <input type="text" id="firstname" name="firstname" className="form-control" placeholder="Enter firstname" onChange={(e)=>{this.handleChange(e)}} />
                  <label htmlFor="firstname">firstname</label>
                  {this.state.firstnameError ? <span style={{color: "red"}}>Please Enter some value</span> : ''} 
                </div>
              </div>
              <div className="form-group">
                <div className="form-label-group">
                  <input type="text" id="lastname" name="lastname" className="form-control" placeholder="Enter lastname" onChange={(e)=>{this.handleChange(e)}} />
                  <label htmlFor="lastname">lastname</label>
                  {this.state.lastnameError ? <span style={{color: "red"}}>Please Enter some value</span> : ''}
                </div>
              </div>
              <div className="form-group">
                <div className="form-label-group">
                  <input type="email" id="email" name="email" className="form-control" placeholder="Enter your email" onChange={(e)=>{this.handleChange(e)}} />
                  <label htmlFor="email">email</label>
                  {this.state.emailError ? <span style={{color: "red"}}>Please Enter valid email address</span> : ''}
                </div>
              </div>                
              <div className="form-group">
                <div className="form-label-group">
                  <input type="password" id="password" name="password" className="form-control" placeholder="Password" onChange={(e)=>{this.handleChange(e)}} />
                  <label htmlFor="password">Password</label>
                  {this.state.passwordError ? <span style={{color: "red"}}>Please enter some   value</span> : ''}
                </div>
              </div>                
              <button className="btn btn-primary btn-block" disabled={this.state.isDisabled} onClick={this.submitForm}>Signup</button>
            </form>
        </div>
      </div>
    </div>
  );
 }
}
export default Signup;
Run Code Online (Sandbox Code Playgroud)


Bru*_*uce 5

使用 React Hook,表单变得超级简单(React Hook Form: https: //github.com/bluebill1049/react-hook-form

我已经重用了你的 html 标记。

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

function Test() {
  const { useForm, register } = useForm();
  const contactSubmit = data => {
    console.log(data);
  };

  return (
    <form name="contactform" onSubmit={contactSubmit}>
      <div className="col-md-6">
        <fieldset>
          <input name="name" type="text" size="30" placeholder="Name" ref={register} />
          <br />
          <input name="email" type="text" size="30" placeholder="Email" ref={register} />
          <br />
          <input name="phone" type="text" size="30" placeholder="Phone" ref={register} />
          <br />
          <input name="address" type="text" size="30" placeholder="Address" ref={register} />
          <br />
        </fieldset>
      </div>
      <div className="col-md-6">
        <fieldset>
          <textarea name="message" cols="40" rows="20" className="comments" placeholder="Message" ref={register} />
        </fieldset>
      </div>
      <div className="col-md-12">
        <fieldset>
          <button className="btn btn-lg pro" id="submit" value="Submit">
            Send Message
          </button>
        </fieldset>
      </div>
    </form>
  );
}
Run Code Online (Sandbox Code Playgroud)


Gal*_*lit 5

2022
\nReact 建议使用 3 种方法来处理表单:

\n
    \n
  1. 受控组件- 在 HTML 中,<input>、<textarea> 和 <select> 等表单元素通常会维护自己的状态并根据用户输入进行更新。在 React 中,可变状态通常保存在组件的 state 属性中,并且仅使用 setState() 进行更新。我们可以通过使 React 状态成为 \xe2\x80\x9c 单一事实来源\xe2\x80\x9d 来将两者结合起来。然后,呈现表单的 React 组件还控制后续用户输入时该表单中发生的情况。以这种方式由 React 控制其值的输入表单元素称为 \xe2\x80\x9c 受控组件\xe2\x80\x9d。

    \n
  2. \n
  3. 不受控组件- 使用受控组件有时可能很乏味,因为您需要为数据可以更改的每种方式编写一个事件处理程序,并通过 React 组件传输所有输入状态。当您将现有代码库转换为 React 或将 React 应用程序与非 React 库集成时,这可能会变得特别烦人。在这些情况下,您可能需要检查不受控制的组件,这是实现输入表单的替代技术。

    \n
  4. \n
  5. 成熟的解决方案- 如果您\xe2\x80\x99正在寻找完整的解决方案,包括验证、跟踪访问的字段以及处理表单提交,Formik是受欢迎的选择之一。然而,它是建立在受控组件和管理状态\xe2\x80\x94相同的原理之上的,所以不要\xe2\x80\x99忽略学习它们。

    \n
  6. \n
\n

所有方法都对反应钩子有效。
\n首先考虑哪个组件更适合您的需求,并使用其适当的验证解决方案。

\n