itsource

React 컴포넌트의 양식에 검증을 추가하려면 어떻게 해야 합니까?

mycopycode 2023. 3. 8. 21:09
반응형

React 컴포넌트의 양식에 검증을 추가하려면 어떻게 해야 합니까?

내 연락처 페이지 양식은 다음과 같습니다.

<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>

모든 필드에 대한 검증을 추가해야 합니다.이 리액션 폼에 검증을 추가할 수 있는 사람이 있습니까?

, .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"));
    

이 예에서는 e-메일 및 이름에 대해서만 검증을 수행했지만, 방법을 알고 있습니다.나머지는 네가 알아서 할 수 있어.

더 좋은 방법이 있을지도 모르지만, 당신은 그 아이디어를 얻을 수 있을 거예요.

여기 바이올린이 있다.

예를 들어, 아래 입력 태그의 필수 속성을 사용하면 이름 필드가 비어 있지 않도록 할 수 있습니다.

<input type="text" placeholder="Your Name" required />

고객님의 코드를 라이브러리 react-form-with-constraints로 수정하였습니다.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>
    );
  }
}

스크린샷:

폼 검증 스크린샷

이것은 빠른 해킹이다.데모를 올바르게 하려면 , https://github.com/tkrotoff/react-form-with-constraints#examples 를 참조해 주세요.

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;

리액트 훅을 사용하면 폼이 매우 간단해집니다(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>
  );
}

리액션에 있다고 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>
  );
}

그러나 복잡한 형식의 경우 각 값을 상태 변수로 유지하고 각 필드에서 검증을 사용하는 것은 어렵습니다.복잡한 폼의 경우 모든 기능을 제공하는 Formik을 사용할 것을 권장합니다.또한 다음 패키지에서 지원되는 Yup 검증 패키지를 사용할 수 있습니다.Formik단순한 검증 이상의 것을 추가할 수 있습니다.

2022
React는 양식을 처리하는 세 가지 방법을 제안합니다.

  1. 제어된 컴포넌트 - HTML 에서는 일반적으로 <input>, <textarea>, <select> 등의 폼 요소는 자체 상태를 유지하고 사용자 입력에 따라 업데이트합니다.React에서는 일반적으로 변경 가능한 상태는 컴포넌트의 상태 속성으로 유지되며 setState()로만 갱신됩니다.반응 상태를 "단일 진실의 원천"으로 함으로써 이 둘을 결합할 수 있습니다.그런 다음 양식을 렌더링하는 React 구성 요소는 후속 사용자 입력 시 해당 양식에서 수행되는 작업도 제어합니다.이러한 방식으로 React에 의해 값이 제어되는 입력 양식 요소를 "제어된 구성 요소"라고 합니다.

  2. 제어되지 않은 구성 요소 - 데이터가 변경되고 React 구성 요소를 통해 모든 입력 상태를 파이핑할 수 있는 모든 방법에 대해 이벤트 핸들러를 작성해야 하므로 제어된 구성 요소를 사용하는 것이 지루할 수 있습니다.이는 기존 코드베이스를 React로 변환하거나 React 응용 프로그램을 비React 라이브러리와 통합하는 경우 특히 번거로울 수 있습니다.이러한 상황에서는 입력 양식을 구현하기 위한 대체 기술인 제어되지 않은 구성요소를 확인하는 것이 좋습니다.

  3. 완전한 솔루션 - 검증, 방문 필드 추적, 폼 제출 처리 등 완전한 솔루션을 찾고 있다면 Formik이 인기 있는 옵션 중 하나입니다.단, 제어된 컴포넌트와 상태 관리라는 동일한 원칙을 기반으로 구축되어 있기 때문에 반드시 학습해 주십시오.

후크를 반응시키기 위해서도, 모든 어프로치가 유효합니다.
먼저 어떤 컴포넌트가 요구에 가장 적합한지 검토하고 적절한 검증 솔루션을 사용합니다.

react js 형식을 검증할 수 있는 많은 옵션이 있습니다.npm 패키지에는 제한이 있을 수 있습니다.필요에 따라 적절한 검증 패키지를 선택할 수 있습니다.아래에 있는 것을 추천하고 싶습니다.

이것보다 더 좋은 해결책을 알고 계신 분은 댓글란에 올려주세요.

보다 깔끔한 방법은 joi-browser 패키지를 사용하는 것입니다.상태에서는 폼의 모든 오류를 포함하는 errors 객체가 있어야 합니다.처음에는 빈 객체로 설정해야 합니다.스키마를 만듭니다.

import Joi from "joi-browser";
schema = {
    username: Joi.string()
      .required()
      .label("Username")
      .email(),
    password: Joi.string()
      .required()
      .label("Password")
      .min(8)
      .regex(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,1024}$/) //special/number/capital
   };

다음으로 스키마를 사용하여 폼을 검증합니다.

validate = () => {
    const options = { abortEarly: false };
    const result = Joi.validate(this.state.data, this.schema, options);
    console.log(data) // always analyze your data
    if (!result.error) return null; 
    const errors = {};
    for (let item of result.error.details) errors[item.path[0]] = item.message; //in details array, there are 2 properties,path and message.path is the name of the input, message is the error message for that input.
    return errors;
  };

양식을 제출하기 전에 다음 양식을 확인하십시오.

handleSubmit = e => {
    e.preventDefault();
    const errors = this.validate(); //will return an object
    console.log(errors);
    this.setState({ errors: errors || {} }); //in line 9 if we return {}, we dont need {} here
    if (errors) return;
    //so we dont need to call the server
    alert("success");
    //if there is no error call the server
    this.dosubmit();
  };

답변이 늦어질 수 있습니다.현재 코드를 많이 수정하지 않고 프로젝트 전체에 동일한 검증 코드를 사용할 수 있다면 https://github.com/vishalvisd/react-validator을 사용해 보십시오.

powerform-react 를 사용해 주세요.에 기초하고 있다powerform휴대용 자바스크립트 폼 라이브러리입니다.학습한 후에는 모든 프레임워크에서 사용할 수 있습니다.자바스크립트

powerform-react를 사용하는 이 간단한 폼을 확인합니다.

복잡한 예도 있다.

사용자 지정 유효성 검사 규칙을 추가할 수 있는 양식에서 이 유효성 검사 플러그인을 사용해 보십시오.

FormValidation 컴포넌트를 만듭니다.js

  import { useState } from "react";

  const FormValidation = ({ validationRules, formInput }) => {
    const [errors, setErrors] = useState(null);

    const validation = () => {
      // define a empty object to store errors.
      let allErrors = {};
      // Run loop on validation object
      Object.keys(validationRules).forEach((name) => {
        // name is the name of input field
        const rulesArr = validationRules[name];

        // Run loop on validation array applied on that input
        rulesArr.forEach((rule) => {
          // Skip if any error message is already stored in allErrors object
          if (!allErrors[name]) {
            let result;
            // If rule is an array than it is a type of a function with parameter
            switch (Array.isArray(rule)) {
              case true: {
                // take the function name and parameter value from rule array
                const [functionName, paramValue] = rule;
                // call validation function

                result = functionName(formInput, name, paramValue);
                break;
              }

              default:
                // call validation function
                result = rule(formInput, name);
                break;
            }
            if (result) {
              // append error in object
              allErrors = { ...allErrors, ...result };
            }
          }
        });
      });

      return allErrors;
    };

    const validate = () =>
      new Promise((resolve, reject) => {
        const errorObj = validation();

        if (Object.keys(errorObj).length === 0) {
          setErrors({});
          resolve("Success");
        } else {
          setErrors(errorObj);
          reject(Error("Some Error Occurred"));
        }
      });

    return { validate, errors, setErrors };
  };

  export const required = (formInputs, inputName) =>
    !formInputs[inputName] && { [inputName]: "This field is required" };

  function emailPattern(email) {
    return String(email)
      .toLowerCase()
      .match(
        /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
      );
  }

  export const email = (formInputs, inputName) =>
    !emailPattern(formInputs[inputName]) && {
      [inputName]: "Please enter valid email",
    };

  export function passwordPattern(formInputs, inputName) {
    const value = formInputs[inputName];

    let error;
    if (value.length < 8) {
      error = "Your password must be at least 8 characters";
    }
    if (value.search(/[a-z]/i) < 0) {
      error = "Your password must contain at least one letter.";
    }
    if (value.search(/[0-9]/) < 0) {
      error = "Your password must contain at least one digit.";
    }

    if (value.search(/[ `!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/) < 0) {
      error = "Your password must contain at least one special character.";
    }

    return (
      error && {
        [inputName]: error,
      }
    );
  }

  export const maxLength = (formInputs, inputName, paramValue) =>
    formInputs[inputName].length > paramValue && {
      [inputName]: `Maximum characters are ${paramValue}`,
    };

  export const minLength = (formInputs, inputName, paramValue) =>
    formInputs[inputName].length < paramValue && {
      [inputName]: `Minimum characters are ${paramValue}`,
    };

  export default FormValidation;

Login.js에 검증을 실장하고 싶다.

    import React, { useState } from "react";
    import { Button, Form } from "react-bootstrap";
    import FormValidation, {
      required,
      email,
      passwordPattern,
    } from "utils/FormValidation";

    const Login = () => {
      const [formInput, setFormInput] = useState({
        email: "",
        password: "",
      });

      const { validate, errors, setErrors } = FormValidation({
        validationRules: {
          email: [required, email],
          password: [required, passwordPattern],
        },
        formInput,
      });

      const handleChange = (e) => {
        setFormInput({ ...formInput, [e.target.name]: e.target.value });
      };

      const handleSubmit = (e) => {
        e.preventDefault();
        validate().then(() => {
          //do whatever you want
          console.log(formInput);
          // you can set server error manually
          setErrors({ email: "Email already exist" });
        });
      };

      return (
        <section className="gradient-form" style={{ backgroundColor: "#eee" }}>
          <div className="container py-5 h-100">
            <div className="row d-flex justify-content-center align-items-center h-100">
              <div className="col-xl-10">
                <div className="card rounded-3 text-black">
                  <div className="row g-0">
                    <div className="col-lg-6">
                      <div className="card-body p-md-5 mx-md-4">
                        <Form onSubmit={handleSubmit}>
                          <p>Please login to your account</p>
                          <Form.Group className="mb-3" controlId="formBasicEmail">
                            <Form.Control
                              type="text"
                              name="email"
                              placeholder="Enter email"
                              onChange={handleChange}
                            />
                            {errors?.email && <span>{errors.email}</span>}
                          </Form.Group>

                          <Form.Group
                            className="mb-3"
                            controlId="formBasicPassword"
                          >
                            <Form.Control
                              type="password"
                              name="password"
                              placeholder="Password"
                              onChange={handleChange}
                            />
                            {errors?.password && <span>{errors.password}</span>}
                          </Form.Group>
                          <Form.Group
                            className="mb-3"
                            controlId="formBasicCheckbox"
                          >
                            <Form.Check type="checkbox" label="Check me out" />
                          </Form.Group>
                          <div className="d-grid gap-2 mb-3">
                            <Button
                              variant="primary"
                              type="submit"
                              className="gradient-custom-2"
                              size="md"
                            >
                              Submit
                            </Button>
                          </div>
                        </Form>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </section>
      );
    };
    export default Login;

이제 검증 어레이 내의 모든 커스텀 함수를 전달할 수 있습니다.

const { validate, errors, setErrors } = FormValidation({
    validationRules: {
      email: [required, email],
      password: [required, passwordPattern, customFunciton],
    },
    formInput,
  });

const customFunciton = (formInputs, inputName) => ({
[inputName]: `This error is from my custom function`,
});

나는 리액션 특화되지 않은 다음 라이브러리를 제안하고 싶다.그러나 양식 유효성 검사를 실행할 수 있는 간편한 구문과 방법을 제공합니다.이 예는 라이브러리 매뉴얼(https://www.simple-body-validator.com/react/validation-quickstart에서 제공하는 리액션 검증 예시입니다.

언급URL : https://stackoverflow.com/questions/41296668/how-do-i-add-validation-to-the-form-in-my-react-component

반응형