Hướng dẫn tạo Login Form React sử dụng Formik

Với việc validate từ client sẽ giúp tăng tốc độ xử lý và hiệu suất của project. Tránh được những lãng phí thời gian không đáng có chỗ người dùng.


1056

Setup Project React

Sử dụng Create React App to để tạo project. Đối với bài viết này, mình sẽ đặt tên project là validate-react-login-form.

npx create-react-app validate-react-login-form

Bạn vào thư mục project, sau đó start và xem kết quả trên browser

cd validate-react-login-form
npm start

Với mục đích của hướng dẫn này, bạn sẽ tạo app React và thao tác với ba tệp: index.js, index.css và ValidatedLoginForm.js.

Cài đặt Formik

Bây giờ chúng ta tạo dự án ban đầu của mình, chúng ta sẽ cài đặt ba packages: Formik, email-validator và Yup.

Formik giúp xử lý xác thực, thông báo lỗi và gửi biểu mẫu dễ quản lý hơn.

Cài đặt Formik như sau

npm install formik

email-validator là package được sử dụng để xác nhận email.

Cài đặt email-validator:

npm install email-validator

Yup là một trình xác nhận schema thường được sử dụng cùng với Formik.

npm install yup

Chúng ta đã cài đặt xong những package cần thiết cho app React, tiếp theo tạo from validate component nào

Tạo Validated Form Component

Bây giờ chúng ta tạo những thứ cơ bản nhất và import vào thư mục gốc để hiển thị.

Để làm được như vậy, chúng ta thực hiện những bước sau

  • Tạo một function component mới
  • Thêm dữ liệu hiển thị vào
  • Import chúng vào file index.js

Tạo file bên trong src và đặt tên ValidatedLoginForm.js. Bên trong file đó thêm hàm như sau component:src/ValidatedLoginForm.js

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

Chúng ta import vào file index.js file:src/index.js

import ValidatedLoginForm from "./ValidatedLoginForm";

Chúng ta tiếp tục tạo form

<ValidatedLoginForm />

Khi bạn import tất cả vào với nhau, index.js sẽ trông như thế này:

import React from "react";
import ReactDOM from "react-dom";
import ValidatedLoginForm from "./ValidatedLoginForm";
function App() {
  return (
    <div className="App">
      <h1>Validated Login Form</h1>
      <ValidatedLoginForm />
    </div>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Bạn sẽ thấy form component hiển thị như sau:

Validated Form Component in CodeSandbox

Bây giờ, chúng ta vào ValidatedLoginForm.js và thêm Formik.

Đầu tiên import Formik, email-validator, và Yup

import { Formik } from "formik";
import * as EmailValidator from "email-validator"; // used when validating with a self-implemented approach
import * as Yup from "yup"; // used when validating with a pre-built solution

Bây giờ, hãy viết tag Formik với các giá trị ban đầu. Hãy nghĩ về các giá trị ban đầu và thiết lập state.

Bạn cũng sẽ cần callback onSubmit. Callback sẽ lấy hai tham số, giá trị và một đối tượng. Các giá trị biểu hiện cho các giá trị đầu vào từ form của bạn. Bạn sẽ thêm một số mã giả ở đây để mô phỏng callback đăng nhập không đồng bộ, sau đó đăng xuất

Trong callback, hãy gọi hàm setSubmmit đã bị hủy từ các tham số thứ hai. Điều này sẽ cho phép bạn bật hoặc tắt button Submit trong khi call login không đồng bộ đang diễn ra:

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

Render Props

Component Formik sử dụng render props để cung cấp các biến và hàm nhất định cho form mà chúng ta tạo.

Nói tóm lại, render props được sử dụng để chuyển các thuộc tính cho các phần tử con của một component. Trong trường hợp này, Formik sẽ chuyển các thuộc tính cho biểu mẫu của bạn.

{props => {
  const {
    values,
    touched,
    errors,
    isSubmitting,
    handleChange,
    handleBlur,
    handleSubmit
  } = props;
  return (
    <div>
      <h1>Validated Login Form</h1>
    </div>
  );
}}

Thêm code vào trong ứng dụng React

import React from "react";
import { Formik } from "formik";
import * as EmailValidator from "email-validator";
import * as Yup from "yup";
const ValidatedLoginForm = () => (
  <Formik
    initialValues={{ email: "", password: "" }}
    onSubmit={(values, { setSubmitting }) => {
      setTimeout(() => {
        console.log("Logging in", values);
        setSubmitting(false);
      }, 500);
    }}
  >
    {props => {
      const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleBlur,
        handleSubmit
      } = props;
      return (
        <div>
          <h1>Validated Login Form</h1>
        </div>
      );
    }}
  </Formik>
);
export default ValidatedLoginForm;

Hiển thị Form

Bây giờ bạn có thể bắt đầu viết mã để hiển thị form. Form có hai đầu vào (email và mật khẩu), nhãn cho buttn Submit

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

onSubmit gọi từ handleSubmit từ props

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

Bạn tùy chỉnh CSS cho file styles.css như bên 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);
  transition: ease-in-out background-color 250ms, ease-in-out color 250ms;
}
button:hover {
  cursor: pointer;
  background-color: white;
  color: rgb(70, 153, 179);
}

Sau đó bạn import style.css vào index. Js

import "./styles.css";

Thêm message vào Validation

Bây giờ, chúng ta sẽ tạo validate input. Đầu tiên xác định điều chúng ta muốn. Với Email, nên được như sau

  • Phải được nhập
  • Nhìn như email thật

Đối với password

  • Cũng phải được nhập
  • Phải có ít nhất 8 kí tự
  • Trong đó chứa ít nhất 1 kí tự số

Chúng ta sẽ tạo ra message theo 2 cách, 1 bằng cách thủ công và 1 bằng cách sử dụng Yup

Tạo message

Đầu tiên chúng ta tạo hàm để validate. Kiểm tra dữ liệu được nhập từ form và trả về object errors có 2 giá trị chính là value và message

Bên trong tag Formik, chúng ta thêm code vào như sau

validate={values => {
  let errors = {};
  errors.email = "Invalid email";
  return errors;
}}

Bây giờ chúng ta thêm Required để chắc rằng form được nhập bất cứ thứ gì

validate={values => {
  let errors = {};
  if (!values.email) {
    errors.email = "Required";
  }
  return errors;
}}

Sau đó sử dụng email-validator để kiểm email có định dạng như email thật.

validate={values => {
  let errors = {};
  if (!values.email) {
    errors.email = "Required";
  } else if (!EmailValidator.validate(values.email)) {
    errors.email = "Invalid email address.";
  }
  return errors;
}}

Bạn cũng cần check password như email

validate={values => {
  let errors = {};
  if (!values.password) {
    errors.password = "Required";
  }
  return errors;
}}

Chúng ta check ít nhất 8 kí tự theo đoạn code sau

validate={values => {
  const passwordRegex = /(?=.*[0-9])/;
  if (!values.password) {
    errors.password = "Required";
  } else if (values.password.length < 8) {
    errors.password = "Password must be 8 characters long.";
  }
  return errors;
}}

Cuối cùng, check password với ít nhất 1 ký tự bằng cách sử dụng regex

validate={values => {
  let errors = {};
  const passwordRegex = /(?=.*[0-9])/;
  if (!values.password) {
    errors.password = "Required";
  } else if (values.password.length < 8) {
    errors.password = "Password must be 8 characters long.";
  } else if (!passwordRegex.test(values.password)) {
    errors.password = "Invalid password. Must contain one number.";
  }
  return errors;
}}

Toàn bộ đoạn code phần check validate như sau

validate={values => {
  let errors = {};
  if (!values.email) {
    errors.email = "Required";
  } else if (!EmailValidator.validate(values.email)) {
    errors.email = "Invalid email address.";
  }
  const passwordRegex = /(?=.*[0-9])/;
  if (!values.password) {
    errors.password = "Required";
  } else if (values.password.length < 8) {
    errors.password = "Password must be 8 characters long.";
  } else if (!passwordRegex.test(values.password)) {
    errors.password = "Invalid password. Must contain one number.";
  }
  return errors;
}}

Password Validation

Chúng ta sử dụng validationSchema của Yup để check như sau

validationSchema={Yup.object().shape({
  email: Yup.string()
    .email()
    .required("Required")
})}

Đối với password code như sau

validationSchema={Yup.object().shape({
  email: Yup.string()
    .email()
    .required("Required"),
  password: Yup.string()
    .required("No password provided.")
    .min(8, "Password is too short - should be 8 chars minimum.")
    .matches(/(?=.*[0-9])/, "Password must contain a number.")
})}

Hãy cùng khám phá sự khác biệt giữa 2 phương thức ngay nào

Hiển thị Validation và Error Messages

Hiện tại, chúng ta đã có logic cho message, việc cần làm là hiển thị chúng. Bạn cần update các thuộc tính input trong form như sau

Chúng ta cần update một số thuộc tính cho email và password như sa

  • value
  • onChange
  • onBlur
  • className

Render Props trong field Email

Chúng ta bắt đầu với việc updatevalueonChange, và onBlur. Thay đổi update thuộc tính từ render props

<input
  id="email"
  name="email"
  type="text"
  placeholder="Enter your email"
  value={values.email}
  onChange={handleChange}
  onBlur={handleBlur}
/>

Bạn có thể touch thuộc tính trước khi báo lỗi

<input
  id="email"
  name="email"
  type="text"
  placeholder="Enter your email"
  value={values.email}
  onChange={handleChange}
  onBlur={handleBlur}
  className={errors.email && touched.email && "error"}
/>

Nếu có lỗi, nó sẽ hiển thị cho user thấy

Field input sẽ trông như sau

<label htmlFor="email">Email</label>
<input
  id="email"
  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>
)}

Render Props trong field Password

Bây giờ tiếp đến là password. Các bước tương tự như email

<label htmlFor="password">Password</label>
<input
  id="password"
  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>
)}

Testing Validation

Đầu tiên với trường hợp không nhập gì cả. Message error sẽ được hiển thị như sau

Validation messages in the login form

Trường hợp khác. Chúng ta click vào input email nhưng không nhập gì cả

Focusing the email field in the login form

Sau đó click ra ngoài input chúng ta sẽ thấy message Required. Mà không cần load lại trang như click button trong trường hợp trên

Email validation error in the login form

Chúng ta nhập không đúng với định dạng email

Invalid email message in the login form

Nhập đúng định dạng email và không thấy lỗi nào hiển thị

Valid email in the login form

Làm điều tương tự với password. Click vào không nhập gì cả và click bên ngoài input

The required password message in the login form

Bạn sẽ nhập password nhưng không đủ độ dài

Bây giờ bạn nhập đủ kí tự nhưng không nhập số

Cuối cùng chúng ta thêm số vào. Và message error không xuất hiện

Kết luận

Qua bài viết bạn có thể tạo form check validation app React, với Formik và Yum.

Tham khảo thêm React : Bí quyết lập trình React cho người mới bắt đầu


Like it? Share with your friends!

1056