簡體   English   中英

如何在反應中進行表單驗證?

[英]How to do form validation in react?

我已經創建了反應形式。 我需要表單驗證方面的幫助。 我創建了自定義驗證。

如代碼所示,我有 2 個相同表單的電子郵件字段。 如果我嘗試在一個字段中輸入電子郵件,則會顯示兩個電子郵件字段的錯誤。 這背后的原因是使用相同的“invalidEmail”狀態屬性。 我不想為每個字段創建單獨的狀態屬性。 與年齡和電話字段相同的情況。

誰能幫我解決這個問題。 如果你有的話,你可以建議我不同的方法。 我不想為驗證添加任何庫或插件。

Codesandbox 鏈接: https ://codesandbox.io/s/heuristic-bartik-1lucn

注意:您可以對此邏輯進行建模,以便為您的 React 項目中的所有字段電子郵件、年齡、電話等開發、編寫更好的最佳實踐

你可以試試這個並編輯你的代碼和框:

添加新狀態: invalidFields用於存儲無效字段:

state = {
    user: {
      name: "",
      email1: "",
      email2: "",
      age: "",
      city: "",
      phone: ""
    },
    invalidNumber: false,
    invalidEmail: false,
    invalidFields: [], // Add this line
    submitted: false
  };

然后在handleChange function編輯您的條件:

將名稱添加到this.validateEmail(value, name);

if (name === "email1") {
  this.validateEmail(value, name); // add name
}
if (name === "email2") {
  this.validateEmail(value, name); // add name
}
if(name === "age") {
  this.validateNumber(value, name); // add name
}
if(name === "phone") {
  this.validateNumber(value, name); // add name
}

然后更改您的validateEmail function :已編輯

validateEmail = (value, name) => {
    const regex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
    if (value && !regex.test(value)) {
      // add invalidFields to this.setState 
      this.setState({ invalidEmail: true, invalidFields: [...this.state.invalidFields, name] });
    } else {
      // add invalidFields to this.setState and then filter
      this.setState({ invalidEmail: false, invalidFields: this.state.invalidFields.filter(item => item !== name) });
    }
  };

最后更改顯示錯誤的條件:已編輯

// email1
{submitted && this.state.invalidFields.includes('email1') && (
    <div style={{ color: "red" }}>Email is invalid</div>
)}

// email2
{submitted && this.state.invalidFields.includes('email2') && (
    <div style={{ color: "red" }}>Email is invalid</div>
 )}

向 state 添加一個新變量,用於跟蹤必填字段是否有效。 使用該變量禁用/啟用提交按鈕。

state = {
 ...
  isValidForm: false
}

validateNumber = value => {
  const regex = /^[0-9]\d*$/;
  return regex.test(value);
};

validateEmail = email => {
  /* eslint-disable-next-line */
  const regexp = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
  return regexp.test(email);
};

handleChange = e => {
  const { name, value } = e.target;
  const { user } = this.state;

  this.setState(
    {
      user: {
        ...user,
        [name]: value
      }
    },
    () => {
      // update the value here
      this.setState({
        isValidForm:
          this.validateEmail(this.state.user.email1) &&
          this.validateEmail(this.state.user.email2) &&
          this.validateNumber(this.state.user.age) &&
          this.validateNumber(this.state.user.phone)
      });
    }
  );
};

然后根據輸入的值禁用/啟用提交按鈕。

<button disabled={!this.state.isValidForm} type="submit">
  Submit
</button>

要在用戶鍵入時顯示錯誤,請在 state 中添加一個存儲觸摸輸入的變量, onFocus input 將焦點輸入名稱添加到數組中。

state = {
 ...
 isTouched: []
}

<div>
  <label htmlFor="email2">Email 2</label>
  <input
    type="email"
    id="email2"
    name="email2"
    onFocus={() => this.isTouched("email2")}
    value={user.email2}
    onChange={this.handleChange}
  />
  {submitted && !user.email2 && (
    <div style={{ color: "red" }}>Email 2 is required</div>
  )}
  {!this.validateEmail(this.state.user.email2) &&
    this.state.isTouched.includes("email2") && (
      <div style={{ color: "red" }}>Email is invalid</div>
    )}
</div>

 .App { font-family: sans-serif; text-align: center; } div { margin: 0 0 10px 0; clear: both; overflow: hidden; } div label { float: left; width: 100px; text-align: left; } div input, div select { float: left; width: 200px; padding: 5px; clear: both; } div div { text-align: left; } button { float: left; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script> <div id="root"></div> <script type="text/babel"> class App extends React.Component { state = { user: { name: "", email1: "", email2: "", age: "", city: "", phone: "" }, invalidNumber: false, invalidEmail: false, submitted: false, isValidForm: false, isTouched: [] }; validateNumber = value => { const regex = /^[0-9]\\d*$/; return regex.test(value); }; validateEmail = email => { /* eslint-disable-next-line */ const regexp = /^\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+$/; return regexp.test(email); }; handleChange = e => { const { name, value } = e.target; const { user } = this.state; this.setState( { user: { ...user, [name]: value } }, () => { this.setState({ isValidForm: this.validateEmail(this.state.user.email1) && this.validateEmail(this.state.user.email2) && this.validateNumber(this.state.user.age) && this.validateNumber(this.state.user.phone) }); } ); }; handleSubmit = e => { e.preventDefault(); const { name, age, email1, email2, city, phone } = this.state.user; this.setState({ submitted: true }); if ( name !== "" && age !== "" && email1 !== "" && email2 !== "" && city !== "" && phone !== "" ) { console.log("User created : ", this.state.user); } else { console.log("Error creating user"); } }; isTouched = inputName => { const inputs = [...this.state.isTouched]; if (!inputs.includes(inputName)) { inputs.push(inputName); this.setState({ isTouched: inputs }); } }; render() { const { submitted, invalidEmail, user } = this.state; return ( <div className="App"> <form onSubmit={this.handleSubmit}> <div> <label htmlFor="name">Name</label> <input type="text" id="name" onFocus={() => this.isTouched("name")} name="name" value={user.name} onChange={this.handleChange} /> {!user.name && this.state.isTouched.includes("name") && ( <div style={{ color: "red" }}>Name is required</div> )} </div> <div> <label htmlFor="age">Age</label> <input type="text" id="age" name="age" onFocus={() => this.isTouched("age")} value={user.age} onChange={this.handleChange} /> {submitted && !user.age && ( <div style={{ color: "red" }}>Age is required</div> )} {!this.validateNumber(user.age) && this.state.isTouched.includes("age") && ( <div style={{ color: "red" }}>Age must be numeric</div> )} </div> <div> <label htmlFor="email1">Email 1</label> <input type="email" id="email1" name="email1" onFocus={() => this.isTouched("email1")} value={user.email1} onChange={this.handleChange} /> {submitted && !user.email1 && ( <div style={{ color: "red" }}>Email 1 is required</div> )} {!this.validateEmail(this.state.user.email1) && this.state.isTouched.includes("email1") && ( <div style={{ color: "red" }}>Email is invalid</div> )} </div> <div> <label htmlFor="email2">Email 2</label> <input type="email" id="email2" name="email2" onFocus={() => this.isTouched("email2")} value={user.email2} onChange={this.handleChange} /> {submitted && !user.email2 && ( <div style={{ color: "red" }}>Email 2 is required</div> )} {!this.validateEmail(this.state.user.email2) && this.state.isTouched.includes("email2") && ( <div style={{ color: "red" }}>Email is invalid</div> )} </div> <div> <label htmlFor="phone">Phone</label> <input type="text" id="phone" name="phone" value={user.phone} onFocus={() => this.isTouched("phone")} onChange={this.handleChange} /> {submitted && !user.phone && ( <div style={{ color: "red" }}>Phone is required</div> )} {!this.validateNumber(user.phone) && this.state.isTouched.includes("phone") && ( <div style={{ color: "red" }}>Phone must be numeric</div> )} </div> <div> <label htmlFor="city">City</label> <select id="city" name="city" value={user.city} onChange={this.handleChange} > <option value="" disabled> Select </option> <option value="Delhi">Delhi</option> <option value="Mumbai">Mumbai</option> <option value="Pune">Pune</option> </select> {submitted && !user.city && ( <div style={{ color: "red" }}>City is required</div> )} </div> <button disabled={!this.state.isValidForm} type="submit"> Submit </button> </form> </div> ); } } ReactDOM.render( <App />, document.getElementById('root') ); </script>

在我看來,擁有兩個獨立的狀態似乎是有道理的。 如果只是為了不想創建另一個狀態,我可能會爭辯說可讀性和簡單性應該是優先事項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM