Cách validate dữ liệu trong Form sử dụng ReactJS + Formik

1
Dịch vụ dạy kèm gia sư lập trình

Đối với lập trình viên front-end, bạn sẽ phải làm việc với form nhập liệu rất nhiều. Bản chất của form là để người dùng có thể gửi thông tin tới server. Có nhiều dạng form như: form đăng nhập, form đăng ký thành viên, form đăng ký khóa học… Theo lẽ thường, cả phía front-end và server để phải validate dữ liệu mà người dùng nhập trước khi xử lý nó.

Trong React, công việc validate dữ liệu trong form nhập liệu có đôi chút phức tạp và dài dòng. Do vậy, để viết code đơn giản hơn, chúng ta sẽ sử dụng thư viện Formik (một thư viện chuyên về tạo form cho React).

Với mục đích vừa học vừa thực hành, bài viết này chúng ta sẽ cùng nhau tiến hành tạo Form validation Reactjs (một form đăng nhập).

Validation là gì?

Trước khi bắt đầu thực hiện dự án, mình muốn nói qua về khái niệm validation. Nếu nói validation thì nó rất rộng, từ validation chất lượng sản phẩm, tới validation dữ liệu…

Cụ thể trong bài viết này, mình muốn nói về validation form trong html. Chúng ta hiểu đơn giản như sau: Validate một cái gì đó là việc kiểm trang cái đó xem có thỏa mãn yêu cầu đặt ra không (phone thì phải là số, email thì phải có @…).

Việc validation sẽ chặn trước các lỗi nhập dữ liệu và bắt buộc người dùng phải nhập form theo đúng yêu cầu.

Các bước thực hiện chính tạo Form validation Reactjs

Nếu bạn ngại đọc bài viết vì quá dài, mình sẽ tóm tắt các bước thực hiện gồm có 4 thao tác chính:

  • Tạo mới một dự án React.
  • Thêm thư viện (hay còn gọi là package) Formik vào dự án.
  • Chỉnh sửa Formik component với onSubmit callback để validate dữ liệu khi người dùng nhấn nút Submit. Hiển thị thông báo nếu gặp lỗi.
  • Hiển thị thông báo nếu có bất kỳ lỗi nào trong quá validate dữ liệu.

Kết quả sau khi hoàn thành bài viết này sẽ được như demo bên dưới đây.

Tạo dự án React

Đối với bài viết này, mình sử dụng CodeSandbox để làm việc với React. Đây là trình Editor online với nhiều tính năng thú vị, như code đến đâu hiển thị kết quả đến đó. Nếu không thích, bạn có thể tạo dự án React theo cách thủ công trên máy tính của bạn cũng được.

💦 Tham khảo thêm: Cách bắt đầu dự án React trên máy tính

Với CodeSandbox, việc tạo mới một dự án ReactJS rất đơn giản. Sau khi đăng ký một tài khoản, trong màn dashboard, nhấn nút “Create Sandbox” -> chọn React

Tạo dự án React trong Codesandbox
Tạo dự án React trong Codesandbox

Cài đặt thư viện cần thiết

Sau khi tạo dự án xong, bước tiếp theo là cài đặt các thư viện cần thiết cho dự án.

  • Formik – hỗ trợ validate, hiển thị thông báo lỗi và submit dữ liệu dễ dàng hơn.
  • Email-validator – một thư viện tý hon hỗ trợ xác thực định dạng địa chỉ email.
  • Yup – là schema validator được sử dụng kết hợp với Formik.

Nếu bạn tạo dự án React trên máy tính trên môi trường Node.js, bạn có thể cài đặt thư viện bằng câu lệnh của npm, ví dụ:

npm install Formik

Còn với CodeSandbox, việc thêm thư viện lại dễ như ăn kẹo vậy. Bạn chỉ cần nhấn nút “Add dependency”, sau tìm đúng thư viện để thêm là được.

Cài đặt thư viện React

Tạo mới Validated Form Component

Như vậy là các thủ tục khởi động đã xong. Giờ chúng ta sẽ bắt tay vào code.

Việc đầu tiên là tạo một component riêng cho validate form. Bỏ qua việc quy hoạch cấu trúc thư mục dự án sao cho đẹp. Để cho đơn giản, chúng ta chỉ đơn giản tạo một component và import nó vào root file (index.js).

Trong bài viết giới thiệu về React Hooks, mình có nhắc đến 2 trường phái tạo component: theo kiểu Class hay kiểu function.

💓 Có ích cho bạn: React Hooks – có gì hấp dẫn?

Bài viết này, mình sẽ tạo ValidatedFormComponent theo kiểu function component nhé.

Trong thư mục src, chúng ta tạo một file đặt tên là ValidatedLoginForm.js. Ban đầu, file này có nội dung như sau:

import React from "react";
const ValidatedLoginForm = () => (
  <div>
    <h1>Validated Form Component</h1>
  </div>
);

export default ValidatedLoginForm;

Sau đó, khai báo component trong index.js

function App() {
  return (
    <div className="App">
      <ValidatedLoginForm />
    </div>
  );
}

Kết quả bạn nhận được như hình bên dưới:

Tạo mới Form validation Reactjs

Tiếp theo, chúng ta khai báo các thư viện trong index.js

import { Formik } from "formik";
import _ as EmailValidator from "email-validator";
import _ as Yup from "yup";

Chúng ta sẽ bắt đầu với Formik tag với các giá trị khởi tạo ban đầu. Ngoài ra, mình cũng tạo một onSubmit callback. Giá trị đầu vào cho onSubmit callback chính là các dữ liệu do người dùng nhập.

Ngoài ra, trong onSubmit callback, mình có đoạn dummy code để giả lập việc gọi hàm login tới server.

<Formik
  initialValues={{ email: "", password: "" }}
  onSubmit={(values, { setSubmitting }) => {
    setTimeout(() => {
      console.log("Logging in", values);
      setSubmitting(false);
    }, 500);
  }}
>
  <h1>Validated Login Form</h1>
</Formik>

Render Props

Formik component sử dụng render props để cung cấp biến và functions cho form mà chúng ta đã tạo. Nếu bạn chưa nghe tới render props bao giờ thì tranh thủ đọc tài liệu giải thích từ nhà sản xuất: Render Props Explained

Hiểu một cách ngắn gọn, render props được sử dụng để truyền các thuộc tính cho các element con của một component.

Trong trường hợp này, Formik sẽ chuyển các thuộc tính (properties) tới form mà chúng ta tạo.

Lưu ý: Chúng ta đang sử dụng destructuring để lấy các tham chiếu tới một biến hay một hàm cụ thể.
{ props => {
      const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleBlur,
        handleSubmit
      } = props;
      return (
        <div>
          <h1>Validated Login Form</h1>
        </div>
      );
    }}

Hiển thị giao diện form đăng nhập

Đến bước này, chúng ta mới thực sự viết code để hiển thị giao diện form đăng nhập.

Form đăng nhập rất đơn giản, chỉ có 2 trường nhập: email và mật khẩu. Ngoài ra, còn thêm một nút submit nữa. Hết

{ props => {
      const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleBlur,
        handleSubmit
      } = props;
      return (
        <form onSubmit={handleSubmit}>
          <label htmlFor="email">Email</label>
          <input name="email" type="text" placeholder="Enter your email" />

          <label htmlFor="email">Password</label>
          <input
            name="password"
            type="password"
            placeholder="Enter your password"
          />
          <button type="submit" >
            Login
          </button>
        </form>
      );
    }}

Ngoài ra, chúng ta có thể thêm một tính năng nho nhỏ đó là tự động disable nút submit trong khi người dùng đang đăng nhập. Cách làm đơn giản là sử dụng dụng thuộc tính isSubmitting mà chúng ta đã destructured từ props ở trên.

<button type="submit" disabled={isSubmitting}>
      Login
  </button>

Về phần CSS, mình cũng không biết giải thích thế nào. Thôi thì bạn cứ copy đoạn CSS mà mình đã tạo sẵn ở đây, rồi đọc hiểu dần dần. Trong thư mục src, tạo mới styles.css rồi dán đoạn code như dưới.

.App {
  font-family: sans-serif;
}

h1 {
  text-align: center;
}

form {
  max-width: 500px;
  width: 100%;
  margin: 0 auto;
}

label,
input {
  display: block;
  width: 100%;
}

label {
  margin-bottom: 5px;
  height: 22px;
}

input {
  margin-bottom: 20px;
  padding: 10px;
  border-radius: 3px;
  border: 1px solid #777;
}

input.error {
  border-color: red;
}

.input-feedback {
  color: rgb(235, 54, 54);
  margin-top: -15px;
  font-size: 14px;
  margin-bottom: 20px;
}

button {
  padding: 10px 15px;
  background-color: rgb(70, 153, 179);
  color: white;
  border: 1px solid rgb(70, 153, 179);
  background-color: 250ms;
}

button:hover {
  cursor: pointer;
  background-color: white;
  color: rgb(70, 153, 179);
}

Xử lý logic khi validate

Bây giờ mới tới tiết mục quan trọng của bài viết. Khi validate một form, chúng ta cần list ra một danh sách các yêu cầu cần phải pass với một trường nhập liệu.

Hãy bắt đầu với form nhập email:

  • Bắt buộc phải nhập, không được để trống.
  • Cấu trúc phải đúng chuẩn email. Tức là phải có @, phải có domain đằng sau ký tự @…

Với form mật khẩu:

  • Bắt buộc phải nhập, không được để trống.
  • Dài ít nhất 8 ký tự.
  • Chứa ít nhất một số.

Tạm thời mình mới liệt kê được như vậy. Các bạn có thể tự nghĩ ra thêm các quy tắc khác nữa.

Khi người dùng nhập dữ liệu mà không đúng với quy tắc trên thì ứng dụng cần phải hiển thị thông báo lỗi. Trong bài viết này, mình sẽ sử dụng Yup để hiển thị thông báo. Bạn thích thì hoàn toàn có thể tự code phần hiển thị thông báo mà không cần tới thư viện.

Với form email, chúng ta có đoạn code validate như dưới đây:

validationSchema={Yup.object().shape({
      email: Yup.string()
        .email()
        .required("Không được để trống")
    })}

Còn với form mật khẩu:

validationSchema={Yup.object().shape({
  email: Yup.string()
    .email()
    .required("Không được để trống "),
  password: Yup.string()
    .required("Chưa nhập mật khẩu.")
    .min(8, "Mật khẩu quá ngắn - ít nhất phải 8 ký tự.")
    .matches(/(?=.*[0-9])/, "Mật khẩu phải chứa nhất một số.")
})}

Xong! 🙂

Hiển thị thông báo lỗi

Bạn đã hoàn thành xong phần logic validate, nếu có lỗi thì bắn thông báo. Giờ nhiệm vụ là hiển thị thông báo đó ra ngoài giao diện.

Chúng ta cần update code các forms một chút. Cụ thể, các thuộc tính dưới đây cần update:

  • value
  • onChange
  • onBlur
  • className

Email

Chúng ta cần cập nhật value, onChange, and onBlur bằng cách sử dụng cách thuộc tính từ render props.

<label htmlFor="email">Email</label>
<input
  name="email"
  type="text"
  placeholder="Enter your email"
  value={values.email}
  onChange={handleChange}
  onBlur={handleBlur}
  className={errors.email && touched.email && "error"}
/>
{errors.email && touched.email && (
  <div className="input-feedback">{errors.email}</div>
)}

Password

Với form mật khẩu hoàn toàn tương tự nhé.

<label htmlFor="email">Password</label>
<input
  name="password"
  type="password"
  placeholder="Enter your password"
  value={values.password}
  onChange={handleChange}
  onBlur={handleBlur}
  className={errors.password && touched.password && "error"}
/>
{errors.password && touched.password && (
  <div className="input-feedback">{errors.password}</div>
)}

Vậy là đã hoàn thành rồi đấy.

Tạm kết

Như vậy là chúng ta đã hoàn thành xong form validation Reactjs. Việc validate chưa bao giờ là dễ dàng cả. Nhưng với sự trợ giúp của Formik và Yub thì mọi thứ đã dễ dàng hơn.

Các bạn có thể tham khảo code hoàn chỉnh form validation Reactjs tại đây .

Sau bài viết này, bạn thấy thế nào về React? Có phức tạp quá không? Để lại cảm nhận bên dưới phần bình luận nhé.

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcTạo Tooltips trong Android không cần code
Bài tiếp theo6 thư viện Machine Learning Javascript giúp học AI nhanh hơn
Tên đầy đủ là Dương Anh Sơn. Tốt nghiệp ĐH Bách Khoa Hà Nội. Mình bắt đầu nghiệp coder khi mà ra trường chẳng xin được việc đúng chuyên ngành. Mình tin rằng chỉ có chia sẻ kiến thức mới là cách học tập nhanh nhất. Các bạn góp ý bài viết của mình bằng cách comment bên dưới nhé !

1
Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Mới nhất Cũ nhất Nhiều voted nhất
Thông báo
Quân
Guest
Quân

Mình cũng đang mày mò về form validation này. Cám ơn đã “thông não” cho mình.