Đố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).
Nội dung chính của bài viết
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
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.
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:
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.
{ 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
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é.
Mình cũng đang mày mò về form validation này. Cám ơn đã “thông não” cho mình.