【问题标题】:How to write proper form validation in react?如何在反应中编写正确的表单验证?
【发布时间】:2021-12-20 13:58:21
【问题描述】:

我一直在我的应用程序中进行表单验证,用户必须提供正确的公司名称 - 全名 - 电话和电子邮件地址。我面临的奇怪行为是:

1 - 当我在未填写任何输入的情况下提交时,我收到了手机的错误消息,即使它不是第一个输入。 2 - 如果没有公司名称的完整表格,也接受它!

import { React, useState, useEffect } from "react";
/*
  *****
  *****
  Import Showcase.scss - 
*/
import "./Showcase.scss";
const Showacase = () => {
  /*
  *****
  *****
  Logic Goes Here
*/

  //State Management

  //Company State
  *const [company, setCompany] = useState();
  **const [companyValue, setCompanyValue] = useState();**
  //name State
  **const [name, setName] = useState();**
  **const [nameValue, setNameValue] = useState();**
  //Phone State
  **const [phone, setPhone] = useState();
  **const [phoneValue, setPhoneValue] = useState();****
  //Email State
  **const [email, setEmail] = useState();**
  **const [emailValue, setEmailValue] = useState();**
  //Hide Inputs
  const [input, setInput] = useState(true);
  // Message State
  const [message, setMessage] = useState(true);
  // SubMessage
  const [subMessage, setSubMessage] = useState(true);
  //InsertLine
  const [line, setLine] = useState(false);
  //Hide Button
  const [btn, setBtn] = useState(true);
  /* Validation State */

  **const [companyValidate, setCompanyValidate] = useState(false);
  **const [nameValidate, setNameValidate] = useState(false);**
  **const [phoneValidation, setPhoneValidation] = useState(false);**
  **const [emailValidate, setEmailValidate] = useState(false);*****
  // OnSubmit
  const onSubmit = (e) => {
    e.preventDefault();
  };

  //onChange Company
  const onChangeCompany = (e) => {
    setCompany(e.target.value);
  };

  //OnClick
  const onClick = (e) => {
    // Company
    **const reCompanyName = /^[a-zA-Z](?:[^0-9\s\x00-\x1F]|[ \t]){1,79}$/;**
    //Name
    **const reName = /[A-Za-z]{1,50}/;**
    // Email Address
    **const reEmail =
      /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/;**
    //Phone number
    **const rePhone = /\+?[0-9]+([0-9]|\/|\(|\)|\-| ){10,}/g;**

    **if (!reCompanyName.test(company)) {
      setCompanyValidate(true);
      return;
    } else {
      setCompanyValidate(false);
    }**

    **if (!reName.test(name)) {
      setNameValidate(true);
      return;
    } else {
      setNameValidate(false);
    }**

    **if (!rePhone.test(phone)) {
      setPhoneValidation(true);
      return;
    } else {
      setPhoneValidation(false);
    }**

    **if (!reEmail.test(email)) {
      setEmailValidate(true);
      return;
    } else {
      setEmailValidate(false);
    }**

    //upComing Phone

    **if (company === "" || phone === "" || email === "" || name === "") {
      return;
    } else {
      /* setting the New Values */
      setCompanyValue(company);
      setNameValue(name);
      setPhoneValue(phone);
      setEmailValue(email);
      /* Clearing the Inputs */
      setCompany("");
      setName("");
      setPhone("");
      setEmail("");
      /* Logic of hidding Items  */
      setInput(false);
      setMessage(false);
      setSubMessage(false);
      setLine(true);
      setBtn(false);
      /* Reset all options after submission after 5 seconds  */
      setTimeout(() => {
        setInput(!false);
        setMessage(!false);
        setSubMessage(!false);
        setLine(!true);
        setBtn(!false);

        setCompanyValidate(false);
        setNameValidate(false);
        setPhoneValidation(false);

        setEmailValidate(false);
      }, 5000);
    }
  };**

  return (
    <>
      {/* Showcase Main  */}
      <div className="Showcase">
        <div className="Container">
          {/* Showcase Main / Applying the flex */}
          <div className="Showcase__inside">
            {/* Right Side / form and logic  */}
            <div className="Showcase__inside--left">
              <div className="Showcase__inside--left--box">
                {/* the Top Message */}
                {message ? (
                  <h1>Find inbound call centers for your company</h1>
                ) : (
                  <h1>Thank you for your request!</h1>
                )}
                {/* the sub Message Message */}
                {subMessage ? (
                  <p className="paragraphWilBeRemovedOnSmallScreen">
                    Use our AI and Big Data driven call center sourcing solution
                  </p>
                ) : (
                  <p className="paragraphAfterSubmission">
                    You’ve taken the first step. Our experts will get in touch
                    with you soon.
                  </p>
                )}
                {/* Inserting the Line */}
                {line ? <hr></hr> : null}
                <form onSubmit={onSubmit}>
                  {/* Company  */}
                  <div className="Showcase__inside--left--box--form">
                    <label for="company">Company </label>
                    {input ? (
                      <div>
                        <input
                          required
                          value={company}
                          onChange={onChangeCompany}
                          type="text"
                          id="company"
                          placeholder="Company"
                          name="company"
                        />
                        {companyValidate ? (
                          <div className="companyValidate">
                            <small>Please provide a valid company name</small>
                          </div>
                        ) : (
                          ""
                        )}
                      </div>
                    ) : (
                      <p>{companyValue}</p>
                    )}
                  </div>
                  {/* Name  */}
                  <div className="Showcase__inside--left--box--form">
                    <label for="Name">Name </label>
                    {input ? (
                      <div>
                        <input
                          required
                          onChange={(e) => setName(e.target.value)}
                          value={name}
                          type="text"
                          id="Name"
                          placeholder="Full name"
                          name="Name"
                        />
                        {nameValidate ? (
                          <div className="nameValidate">
                            <small>Please Provide a valid Full Name</small>
                          </div>
                        ) : (
                          ""
                        )}
                      </div>
                    ) : (
                      <p>{nameValue}</p>
                    )}
                  </div>
                  {/* Phone  */}
                  <div className="Showcase__inside--left--box--form">
                    <label for="Phone">Phone </label>
                    {input ? (
                      <div>
                        <input
                          required
                          onChange={(e) => setPhone(e.target.value)}
                          value={phone}
                          type="number"
                          id="Phone"
                          placeholder="+49"
                          name="phone"
                        />
                        {phoneValidation ? (
                          <div className="phoneValidation">
                            <small>Please Provide a valid Phone Number</small>
                          </div>
                        ) : (
                          ""
                        )}
                      </div>
                    ) : (
                      <p>{phoneValue}</p>
                    )}
                  </div>
                  {/* Email  */}
                  <div className="Showcase__inside--left--box--form">
                    <label for="Email">Email </label>
                    {input ? (
                      <div>
                        <input
                          required
                          onChange={(e) => setEmail(e.target.value)}
                          value={email}
                          type="email"
                          id="Email"
                          placeholder="name@mail.com"
                          name="email"
                        />
                        {emailValidate ? (
                          <div className="EmailValidate">
                            <small>Please Provide a valid Email</small>
                          </div>
                        ) : (
                          ""
                        )}
                      </div>
                    ) : (
                      <p>{emailValue}</p>
                    )}
                  </div>
                  {/* Submit  */}
                  <div className="Showcase__inside--left--box--form">
                    <div className="Showcase__inside--left--box--form--submit">
                      {/* OnClick Method */}
                      {btn ? (
                        <button onClick={onClick} type="submit">
                          Get informed
                        </button>
                      ) : null}
                    </div>
                  </div>
                </form>
              </div>
            </div>
            {/* Right SIDE %s  */}
            <div className="Showcase__inside--right">
              <div>
                <div>
                  <h1>Welcome to Europe’s largest call center database </h1>
                </div>
                <div className="Showcase__inside--right--per">
                  <div className="Showcase__inside--right--per--single">
                    <small>500+</small>
                    <h1>Tenders</h1>
                  </div>
                  <div className="Showcase__inside--right--per--single">
                    <small>200+</small>
                    <h1>Callcenter</h1>
                  </div>
                  <div className="Showcase__inside--right--per--single">
                    <small>375.000</small>
                    <h1>Agents available</h1>
                  </div>
                  <div className="Showcase__inside--right--per--single">
                    <small>85%</small>
                    <h1>Faster sourcing</h1>
                  </div>
                </div>
              </div>
            </div>
            {/* Right Ended %s  */}
          </div>
        </div>
      </div>
    </>
  );
};
export default Showacase;

【问题讨论】:

    标签: javascript reactjs regex


    【解决方案1】:

    我知道这可能有点离题,但我建议您使用一种模式来构建和验证表单。尤其是那些多个 useState 使用起来可能有点麻烦。

    我倾向于在我的代码中使用的通常是这样的:

    let [model, setModel] = useState({firstName: '', lastName: '', ...})
    let validations = {
       firstName: ['required'], 
       ...
    }
    
    return <Form model={model} setModel={setModel} validations={validations}>
       <Field name="firstName" />
       <Field name="lastName" />
       <Submit>Send form</Submit>
    
    </Form>
    

    这通常要短得多,有助于整个应用程序的一致性。

    如果您想要表单、字段等的示例实现,您可以使用我的示例:

    import { cloneElement, useState } from "react";
    
    export function Form({ model, setModel, validations, children, onSubmit, className }) {
      let [errors, setErrors] = useState({});
    
      function computeFieldErrors(fieldName, fieldValue) {
        let fieldValidations = validations[fieldName] || [];
    
        let fieldErrors = [];
    
        for (let validation of fieldValidations) {
          if (validation == "required") {
            if (!fieldValue) fieldErrors.push("Must not be empty");
          } else if (validation instanceof Array) {
            if (validation[0] == "matches") {
              if (fieldValue != model[validation[1]]) {
                fieldErrors.push("Does not match " + validation[1]);
              }
            } else {
              alert("unknown validation: " + validation[0]);
            }
          } else {
            alert("unknown validation: " + validation);
          }
        }
    
        return fieldErrors;
      }
    
      function validateForm() {
        let hasErrors = false;
    
        let res = { ...errors };
    
        for (let fieldName in model) {
          let fieldErrors = computeFieldErrors(fieldName, model[fieldName]);
          if (fieldErrors.length > 0) {
            hasErrors = true;
            res = { ...res, [fieldName]: fieldErrors };
          }
        }
    
        setErrors(res);
    
        if (!hasErrors) onSubmit(model);
      }
    
      function setData(fieldName, fieldValue) {
        setModel({ ...model, ...{ [fieldName]: fieldValue } });
    
        setErrors({ ...errors, [fieldName]: computeFieldErrors(fieldName, fieldValue) });
      }
    
      function fixChildren(nodes) {
        return nodes.map((child, i) => {
          if (child.type) {
            if (child.type.name == "Field") {
              return cloneElement(child, {
                key: i,
                data: model[child.props.name],
                errors: errors[child.props.name],
                setData: (value) => setData(child.props.name, value)
              });
            } else {
              return cloneElement(child, {
                key: i,
                children: child.props.children
                  ? fixChildren(child.props.children instanceof Array ? child.props.children : [child.props.children])
                  : null
              });
            }
          }
          else{
            return child;
          }
        });
      }
    
      return (
        <form
          className={'form ' +  className}
          onSubmit={(event) => {
            event.preventDefault();
            validateForm();
          }}
        >
          {fixChildren(children)}
        </form>
      );
    }
    
    export function Field({ type, name, label, data, setData, errors, component, disabled, placeholder }) {
      if (!component) {
        if (type == "textarea") {
          component = ({ data, setData }) => (
            <textarea
              id={name}
              value={data}
              onChange={(e) => setData(e.target.value)}
              disabled={disabled}
              defaultValue={data}
              placeholder={placeholder}
            ></textarea>
          );
        } else {
          component = ({ data, setData }) => (
            <input
              type={type || "text"}
              id={name}
              value={data}
              placeholder={placeholder}
              onChange={(e) => setData(e.target.value)}
              disabled={disabled}
            />
          );
        }
      }
    
      return (
        <div className={"field " + ((errors || []).length > 0 ? "field--witherrors" : "")}>
          <div className={"field__data"}>
            <div className={"field__label"}>
              <label htmlFor={name}>{label}</label>
            </div>
            <div className={"field__control"}>{component({ data, setData })}</div>
          </div>
          <div className={"field__errors"}>
            <span>{(errors || []).join(", ")}</span>
          </div>
        </div>
      );
    }
    
    export function Submit({children}) {
      return <button type={"submit"}>{children}</button>;
    }
    

    【讨论】:

      【解决方案2】:

      我建议使用诸如 formik 或 react-hooks-form(来自 npm)之类的库。

      表单及其验证是 Web 应用程序的重要组成部分,虽然您可以自己编写,但我建议您从经过良好测试的库中获得帮助。

      【讨论】:

      • 我不允许使用库
      猜你喜欢
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 2021-01-22
      • 1970-01-01
      • 2015-06-05
      • 1970-01-01
      相关资源
      最近更新 更多