sử dụng form validate

cách validate react functional - sử dụng react form input

2021-08-10 2268 lượt xem

validate form hero validate

form trong react

Form nhập liệu là 1 thành phần quan trọng trong 1 website. nhờ có form mà chúng ta có thể thu thập dữ liệu từ phía người dùng. Từ đó đưa ra phân tích và xử lý tương ứng. 
Vì vậy mà react cũng không thể thiếu form. Để thêm thành phần form vào trong react ta có thể xem qua ví dụ đơn giản sau:

import { useState } from "react";
import "./styles.css";

export default function App() {
  const [values, setValues] = useState({ email: "", password: "" });

  /// add function when value change
  const handleChange = (event) => {
    event.persist();

    setValues({ ...values, [event.target.name]: event.target.value });
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log("chưa xử lý gì cả");
  };

  const stringJson = JSON.stringify(values);
  return (
    <div className="App">
      <h1>giới thiệu form react</h1>
      <form onSubmit={handleSubmit}>
        <p>nhập email:</p>
        <input
          name="email"
          type="text"
          defaultValue={values.email}
          onChange={handleChange}
        />
        <p>nhập password:</p>
        <input
          name="password"
          type="text"
          defaultValue={values.password}
          onChange={handleChange}
        />
        <p>bấm submit form</p>
        <button>submit nè</button>
      </form>
      <div className="show-json-string-setValues">{stringJson}</div>
    </div>
  );
}

kết quả ở đây: https://codesandbox.io/s/gioi-thieu-form-functional-5h0dy?file=/src/App.js

khi giá trị input thay đổi thì hàm onChange sẽ được chạy. hàm onChange mục đích là cập nhật lại giá trị của form => khi mình có giá trị của input thì mình sẽ validate nó bằng 1 hàm mình tự define

Chúng ta sẽ thêm state errors để nhận các lỗi và nhờ có nó mà show ra lỗi cho người dùng thấy.

const [errors, setErrors] = useState([]);

Thêm 1 đoạn jsx để hiện thị lỗi

{errors.map((error) => (
        <p key={error}>Error: {error}</p>
      ))}

Hàm validate để get all lỗi.

function validate() {
    const { email, password } = values;
    // we are going to store errors for all fields
    // in a signle array
    const errors = [];

    if (email.length < 5) {
      errors.push("Email should be at least 5 charcters long");
    }
    if (email.split("").filter((x) => x === "@").length !== 1) {
      errors.push("Email should contain a @");
    }
    if (email.indexOf(".") === -1) {
      errors.push("Email should contain at least one dot");
    }
    if (password.length < 6) {
      errors.push("Password should be at least 6 characters long");
    }
    return errors;
  }

sửa hàm handleSubmit để bắt sự kiện khi nào check lỗi.

const handleSubmit = (event) => {
    event.preventDefault();
    const errors = validate();
    if (errors.length > 0) {
      setErrors(errors);
      return;
    }
    // submit the data...
  };

Tất cả có trong code sau :  https://codesandbox.io/s/validate-code-react-thu-cong-bc7k9?file=/src/App.js:0-1944

import { useState } from "react";
import "./styles.css";

export default function App() {
  const [values, setValues] = useState({ email: "", password: "" });
  const [errors, setErrors] = useState([]);

  /// add function when value change
  const handleChange = (event) => {
    event.persist();

    setValues({ ...values, [event.target.name]: event.target.value });
  };

  function validate() {
    const { email, password } = values;
    // we are going to store errors for all fields
    // in a signle array
    const errors = [];

    if (email.length < 5) {
      errors.push("Email should be at least 5 charcters long");
    }
    if (email.split("").filter((x) => x === "@").length !== 1) {
      errors.push("Email should contain a @");
    }
    if (email.indexOf(".") === -1) {
      errors.push("Email should contain at least one dot");
    }
    if (password.length < 6) {
      errors.push("Password should be at least 6 characters long");
    }
    return errors;
  }

  const handleSubmit = (event) => {
    event.preventDefault();
    const errors = validate();
    if (errors.length > 0) {
      setErrors(errors);
      return;
    }
    // submit the data...
  };

  const stringJson = JSON.stringify(values);
  return (
    <div className="App">
      {errors.map((error) => (
        <p key={error}>Error: {error}</p>
      ))}
      <h1>giới thiệu form react</h1>
      <form onSubmit={handleSubmit}>
        <p>nhập email:</p>
        <input
          name="email"
          type="text"
          defaultValue={values.email}
          onChange={handleChange}
        />
        <p>nhập password:</p>
        <input
          name="password"
          type="text"
          defaultValue={values.password}
          onChange={handleChange}
        />
        <p>bấm submit form</p>
        <button>submit nè</button>
      </form>
      <div className="show-json-string-setValues">{stringJson}</div>
    </div>
  );
}

Nhận xét

Nếu sử dụng phương pháp trên thì 
Có 1 điểm lợi là chúng ta tự chủ động các hàm validate, code của chúng ta nên dễ hiểu và dễ nâng cấp
Bên cạnh đó cũng có khuyết điểm là 

  1. component sẽ khá dài 
  2. cái validate cũng được chúng ta tạo 1 cách thủ công, tự viết code dẫn đến trùng lặp code khá nhiều

Sử dụng thư viện validate hero-validate

Installation

npm install hero-validate --save
#or
yarn add hero-validate

Cách sử dụng

/// khai báo thư viện 
const Validation = require('hero-validate');
/// để validate được cần cung cấp các rule giống giống như bạn đang validate jquery
const rules = {
    email        : "required|email|min:2|max:50",
    password     : "required|min:8|max:100",
};
/// thư viện này có set message giống jquery luôn
Validation.setMessages({
    email: {
        required: "Thử override message nè , email còn thiếu",
        min: "trường :name không được nhỏ hơn :min --- override message", /// cái :name sẽ là tên field mà bạn đang dùng còn :min là pagram truyền vào
    },
    required: 'required override message', /// default message of rule required not define field 
    min: 'validator got parameter :min and value :value' /// default message of rule min not define field 
    ....
})
const data = {
  name    : 'Trương Thanh Hùng Đẹp Trai',
  email   : 'thanhhungdevgmail.com',
  password: 'ahihi@1',
};

const result = Validation.validate( data,  rules );
console.log(JSON.stringify(result))
/// {"hasError":true,"errors":{"email":["email phải là mail hợp lệ"],"password":["password phải lớn hơn hoặc bằng 8."]}}

result.isError('name', 'ruleName' ); // Boolean Get if given field has error, ruleName default null will get all

result.getError('name', '-'); // will Get first error message of field or join error string by - character. Default join string error by `,`

result.getAllError('name', "|"); //  will Get all error message of field or join error string by | character. Default join string error by `,`

Cách validate với react functional

đây là code react sanbox nè: https://codesandbox.io/embed/sweet-cache-x6keg?fontsize=14&hidenavigation=1&theme=dark

import React, { useState, useEffect } from "react";
import Validator from "hero-validate";
/// create rule for your form
const rules = {
    email: "required|email|min:8|max:20",
    password: "required|min:7|max:40"
};
Validator.setLocale(Validator.languages.vi)
/// custom message for your form
Validator.setMessages({
    email: "sfsdfds :name ",
    password: {
        min: "sdfsdf password min"
    }
});

export default function TestMyValidate() {
    const [values, setValues] = useState({ email: "", password: "" });
    const [touched, setTouched] = useState({email: false, password: false});
    const [errors, setErrors] = useState(Validator.getEmpty());

    /// add function error custom
    const hasErr = (name) => {
        return touched[name] && errors.isError(name);
    };
    /// add function when value change
    const handleChange = (event) => {
        event.persist();
        setTouched({ ...touched, [event.target.name]: true });
        setValues({ ...values, [event.target.name]: event.target.value });
    };
    /// hook react
    useEffect(() => {
        setErrors(Validator.validate(values, rules));
    }, [values]);

    return (
        <div className="App">
            <form>
                <label htmlFor="email"> mail of u </label>
                <input
                    type="text"
                    className={hasErr("email") ? "error" : ""}
                    name="email"
                    value={values.email}
                    onChange={handleChange}
                />
                { hasErr("email") && (
                    <div className="text-red">{errors.getError("email")}</div>
                )}

                <label htmlFor="password"> password of you </label>
                <input
                    type="password"
                    className={hasErr("password") ? "error" : ""}
                    name="password"
                    value={values.password}
                    onChange={handleChange}
                />
                { hasErr("password") && (
                    <div className="text-red">{errors.getError("password")}</div>
                )}
            </form>
        </div>
    );
}