So sánh các thư viện React Form: SurveyJS, Formik, React Hook Form, React Final Form và Unform

theanh

Administrator
Nhân viên
Bài viết này đã nhận được sự hỗ trợ nhiệt tình của những người bạn thân thiết của chúng tôi tại SurveyJS. Một bộ sản phẩm gồm các thành phần phía máy khách JavaScript nguồn mở được thiết kế để đơn giản hóa việc tạo ra một hệ thống quản lý biểu mẫu toàn chu kỳ được tích hợp hoàn toàn vào cơ sở hạ tầng CNTT của bạn.



Làm việc với dữ liệu đầu vào của người dùng luôn là một trong những phần quan trọng nhất khi phát triển bất kỳ trang web nào. Việc xử lý các vấn đề như xác thực biểu mẫu, gửi và hiển thị lỗi có thể trở nên phức tạp, do đó, sử dụng các giải pháp biểu mẫu hiện có có thể là giải pháp khả thi và có một số giải pháp để xử lý biểu mẫu trong React.

Trong bài viết này, chúng ta sẽ xem xét SurveyJS, Formik, React Hook Form, React Final Form và Unform. Chúng ta sẽ so sánh cách sử dụng chúng, cách tích hợp chúng vào các thành phần UI tùy chỉnh và cách thiết lập các trường phụ thuộc với chúng. Trên đường đi, chúng ta cũng sẽ tìm hiểu cách xác thực biểu mẫu bằng Yup, một trình xác thực lược đồ đối tượng JavaScript.

Bài viết này hữu ích cho những ai muốn biết các thư viện biểu mẫu tốt nhất để sử dụng cho các ứng dụng trong tương lai.

Lưu ý: Bài viết này yêu cầu bạn phải hiểu cơ bản về React và Yup.

Bạn có nên sử dụng thư viện biểu mẫu không?​

Biểu mẫu là một phần không thể thiếu trong cách người dùng tương tác với web. Chúng được sử dụng để thu thập dữ liệu để xử lý từ người dùng và nhiều trang web hiện nay có một hoặc nhiều biểu mẫu. Mặc dù biểu mẫu có thể được xử lý trong React bằng cách biến chúng thành các thành phần được kiểm soát, nhưng việc xây dựng nhiều biểu mẫu có thể trở nên nhàm chán với nhiều mã lặp lại. Bạn có thể liên hệ với một trong nhiều thư viện biểu mẫu có trong hệ sinh thái React. Các thư viện này giúp việc xây dựng các biểu mẫu có độ phức tạp khác nhau trở nên dễ dàng hơn vì chúng cung cấp khả năng xác thực và quản lý trạng thái ngay khi cài đặt, cùng với nhiều tính năng xử lý biểu mẫu hữu ích khác.

Các yếu tố cần cân nhắc​

Biết các thư viện biểu mẫu khác nhau có sẵn là một chuyện, nhưng biết thư viện nào phù hợp để sử dụng cho dự án tiếp theo của bạn lại là chuyện khác. Trong bài viết này, chúng ta sẽ xem xét cách các thư viện biểu mẫu này hoạt động và so sánh chúng dựa trên các yếu tố sau:
  • Triển khai
    Chúng ta sẽ xem xét các API của chúng và cân nhắc xem việc tích hợp chúng vào ứng dụng, xử lý xác thực biểu mẫu, gửi biểu mẫu và trải nghiệm chung của nhà phát triển dễ dàng như thế nào.
  • Sử dụng với các thành phần tùy chỉnh
    Việc tích hợp các thư viện này với các đầu vào từ các thư viện UI như Material UI dễ dàng như thế nào?
  • Các trường phụ thuộc
    Bạn có thể muốn hiển thị trường biểu mẫu B phụ thuộc vào giá trị của trường A. Làm thế nào chúng ta có thể xử lý trường hợp sử dụng đó với các thư viện này?
  • Đường cong học tập
    Bạn có thể bắt đầu sử dụng các biểu mẫu này nhanh như thế nào? Có bao nhiêu tài nguyên học tập và ví dụ có sẵn trực tuyến?
  • Kích thước gói
    Chúng tôi luôn muốn các ứng dụng của mình có hiệu suất cao. Có những sự đánh đổi nào về kích thước gói của các biểu mẫu này?
Chúng ta cũng sẽ xem xét cách tạo biểu mẫu nhiều bước bằng các thư viện này. Tôi đã không thêm điều đó vào danh sách ở trên do cách tôi cấu trúc bài viết. Chúng ta sẽ xem xét điều đó ở cuối bài viết.

Thư viện biểu mẫu React của SurveyJS​

Thư viện biểu mẫu SurveyJS là một thành phần phía máy khách mã nguồn mở hiển thị các biểu mẫu động được điều khiển bằng JSON trong các ứng dụng React. Nó sử dụng các đối tượng JSON để giao tiếp với máy chủ. Các đối tượng này, còn được gọi là lược đồ JSON, xác định các khía cạnh khác nhau của biểu mẫu, bao gồm kiểu, nội dung, bố cục và hành vi của biểu mẫu để phản hồi các tương tác của người dùng, chẳng hạn như gửi dữ liệu, xác thực đầu vào, thông báo lỗi, v.v.

Thư viện có hỗ trợ gốc cho React. Nó miễn phí để sử dụng và được phân phối theo giấy phép MIT. Dòng sản phẩm SurveyJS cũng bao gồm trình tạo biểu mẫu JSON tự lưu trữ có giao diện người dùng kéo và thả, Trình chỉnh sửa chủ đề CSS và GUI cho logic có điều kiện và phân nhánh biểu mẫu.

Tính năng​

Cách cài đặt​

Mã:
npm install survey-react-ui --save

Cách sử dụng​

Mã:
import 'survey-core/defaultV2.min.css';import { Model } from 'survey-core';import { Survey } from 'survey-react-ui';const surveyJson = { các phần tử: [{ name: "FirstName", title: "Nhập tên của bạn:", type: "text" }, { name: "LastName", title: "Nhập họ của bạn:", type: "text" }]};function App() { const survey = new Model(surveyJson); return ;}export default App;
Thư viện biểu mẫu SurveyJS cho React bao gồm hai gói npm: survey-core (mã độc lập với nền tảng) và survey-react-ui (mã kết xuất). Chạy lệnh npm install survey-react-ui --save để cài đặt survey-react-ui. Gói survey-core sẽ được cài đặt tự động dưới dạng phụ thuộc. Một lợi thế khác của SurveyJS là tích hợp liền mạch với các thư viện UI tùy chỉnh và các thành phần biểu mẫu của chúng. hướng dẫn chuyên dụng này trình bày cách tích hợp thành phần React Color vào biểu mẫu SurveyJS cơ bản.

Để thêm chủ đề SurveyJS vào ứng dụng của bạn, hãy mở thành phần React sẽ hiển thị biểu mẫu và nhập bảng kiểu Thư viện biểu mẫu import 'survey-core/defaultV2.min.css';. Bảng kiểu này áp dụng chủ đề Mặc định. Bạn cũng có thể áp dụng một chủ đề được xác định trước khác hoặc tạo một chủ đề tùy chỉnh.

Tiếp theo, bạn cần tạo một mô hình mô tả bố cục và nội dung của biểu mẫu. Các mô hình được chỉ định bởi lược đồ mô hình (đối tượng JSON). Trang web SurveyJS cung cấp bản demo trình tạo biểu mẫu JSON đầy đủ tính năng mà bạn có thể sử dụng để tạo lược đồ JSON cho biểu mẫu của mình. Trong ví dụ này, lược đồ mô hình khai báo hai câu hỏi dạng văn bản, mỗi câu hỏi có tiêu đềtên. Người trả lời có thể nhìn thấy tiêu đề, trong khi tên được sử dụng để xác định các câu hỏi trong mã. Để khởi tạo một mô hình, hãy truyền lược đồ mô hình cho hàm tạo Model như được hiển thị trong mã ở trên.

Để hiển thị biểu mẫu, hãy nhập thành phần Survey, thêm thành phần này vào mẫu và truyền phiên bản mô hình mà bạn đã tạo ở bước trước đó vào thuộc tính model của thành phần.

Kết quả là, bạn sẽ thấy biểu mẫu sau:
Xem thêm tại đâyXem toàn bộ mã nguồn trên GitHub

Formik​

Formik là một thư viện linh hoạt. Bạn có thể chọn sử dụng Formik với các thành phần HTML gốc hoặc với các thành phần tùy chỉnh của Formik. Bạn cũng có tùy chọn thiết lập các quy tắc xác thực biểu mẫu của mình hoặc giải pháp của bên thứ ba như Yup. Nó cho phép bạn quyết định khi nào và sử dụng bao nhiêu. Chúng ta có thể kiểm soát mức độ chức năng của thư viện Formik mà chúng ta sử dụng.

Formik xử lý những công việc lặp đi lặp lại và khó chịu — theo dõi các giá trị, lỗi, trường đã truy cập, sắp xếp xác thực và xử lý việc gửi — để bạn không phải làm những việc đó. Điều này có nghĩa là bạn sẽ mất ít thời gian hơn để thiết lập trạng thái biểu mẫu và trình xử lý onChangeonBlur.

Cài đặt​

Mã:
npm i formikyarn add formik

Triển khai​

Formik theo dõi trạng thái biểu mẫu của bạn và sau đó hiển thị trạng thái đó cùng với một số phương thức có thể tái sử dụng và trình xử lý sự kiện (handleChange, handleBlurhandleSubmit) vào biểu mẫu của bạn thông qua props. Bạn có thể tìm hiểu thêm về các phương pháp có sẵn trong Formik tại đây.

Mặc dù Formik có thể được sử dụng cùng với các trường nhập liệu gốc của HTML, Formik đi kèm với một thành phần Trường mà bạn có thể sử dụng để xác định trường nhập liệu bạn muốn và một thành phần ErrorMessage xử lý việc hiển thị lỗi cho từng trường nhập liệu. Hãy cùng xem chúng hoạt động như thế nào trong thực tế.
Xem thêm tại đây
Mã:
import { Form, Field, ErrorMessage, withFormik } from "formik";const App = ({ values }) => (   Formik Form    Email     Chọn màu để tiếp tục            Chấp nhận Điều khoản & Điều kiện       Một    Hai     Đăng nhập   );
Trong đoạn mã trên, chúng ta đang làm việc với bốn trường nhập, một email, một select, một checkbox và một trường radio. Form là một wrapper nhỏ xung quanh một phần tử HTML tự động móc vào handleSubmithandleReset của Formik. Chúng ta sẽ xem withFormik thực hiện những gì tiếp theo.
Mã:
import { Form, Field, ErrorMessage, withFormik } from "formik";import * as Yup from "yup";const App = ({ values }) => (   Formik Form   //nhập form ở đây  Đăng nhập   );const FormikApp = withFormik({ mapPropsToValues: ({ email, select, checkbox, radio }) => { return { email: email || "", select: select || "", checkbox: checkbox || false, radio: radio || "", }; }, validationSchema: Yup.object().shape({ select: Yup.string().required("Màu là bắt buộc!"), email: Yup.string().email().required("Email là bắt buộc"), checkbox: Yup.bool().oneOf([true], "Hộp kiểm là bắt buộc"), radio: Yup.string().required("Radio là bắt buộc!"), }), handleSubmit: (values) => { alert(JSON.stringify(values)); },})(App);export default FormikApp;
withFormik là HOC inject ngữ cảnh Formik vào trong thành phần được bao bọc. Chúng ta có thể truyền đối tượng options vào withFormik, tại đó chúng ta định nghĩa hành vi của ngữ cảnh Formik.

Formik hoạt động tốt với Yup trong việc xử lý xác thực biểu mẫu, do đó chúng ta không phải thiết lập các quy tắc xác thực tùy chỉnh. Chúng ta định nghĩa một lược đồ để xác thực, truyền nó đến validationSchema. Với mapPropsToValues, Formik chuyển trạng thái đã cập nhật của các trường đầu vào và cung cấp các giá trị cho thành phần App thông qua các props dưới dạng props.values. Hàm handleSubmit xử lý việc gửi biểu mẫu.

Sử dụng với các thành phần tùy chỉnh​

Một lợi ích khác của Formik là việc tích hợp các thư viện UI tùy chỉnh và các thành phần biểu mẫu của chúng rất dễ dàng. Ở đây, chúng tôi thiết lập một biểu mẫu cơ bản bằng cách sử dụng thành phần TextField của Material UI.
Mã:
import TextField from "@material-ui/core/TextField";import * as Yup from "yup";import { Formik, Form, Field, ErrorMessage } from "formik";const signInSchema = Yup.object().shape({ email: Yup.string().email().required("Email là bắt buộc"),});export default function SignIn() { const classes = useStyles(); trả về (    { alert(JSON.stringify(values)); }} > {({ errors, values, handleChange, handleBlur, handleSubmit, reached, }) => (   submit  )}    );}
Field tự động kết nối các đầu vào với Formik. Formik inject các prop onChange, onBlur, namevalue vào thành phần TextField. Nó cũng làm như vậy với bất kỳ loại thành phần tùy chỉnh nào mà bạn quyết định sử dụng. Chúng ta truyền TextField cho Field thông qua prop as của nó.

Chúng ta cũng có thể sử dụng thành phần TextField của Material UI trực tiếp. Tài liệu cũng cung cấp một ví dụ bao gồm tình huống đó.

Các trường phụ thuộc​

Để thiết lập các trường phụ thuộc trong Formik, chúng ta truy cập giá trị đầu vào mà chúng ta muốn theo dõi thông qua đối tượng values trong các đạo cụ kết xuất. Ở đây, chúng ta đang theo dõi trường remember, là hộp kiểm và kết xuất thông báo dựa trên trạng thái của trường.
Mã:
{values.remember && ( 
 Cảm ơn bạn đã chấp nhận các điều khoản của chúng tôi. Bây giờ bạn có thể gửi biểu mẫu 
)}

Learning Curve​

tài liệu của Formik rất dễ hiểu và đi thẳng vào vấn đề. Tài liệu này đề cập đến một số trường hợp sử dụng, bao gồm cách sử dụng Formik với các thư viện UI của bên thứ ba như Material UI. Ngoài ra còn có một số tài nguyên từ cộng đồng Formik để hỗ trợ việc học của bạn.

Kích thước gói​

Formik có dung lượng 44,4kb đã thu nhỏ và 13,1kb đã nén.


React Hook Form​

React Hook Form, hay RHF là một thư viện biểu mẫu nhẹ, không phụ thuộc và linh hoạt được xây dựng cho React.

Cài đặt​

Mã:
npm i react-hook-formyarn add react-hook-form

Triển khai​

RHF cung cấp một hook useForm mà chúng ta có thể sử dụng để làm việc với các biểu mẫu.
Xem thêm tại đây
Chúng ta bắt đầu bằng cách thiết lập các trường nhập HTML cần thiết cho biểu mẫu này. Không giống như Formik, RHF không có thành phần Field tùy chỉnh, vì vậy chúng ta sẽ sử dụng các trường nhập gốc của HTML.
Mã:
import { useForm } from "react-hook-form";const validationSchema = Yup.object().shape({ select: Yup.string().required("Màu là bắt buộc!"), email: Yup.string().email().required("Email là bắt buộc"), checkbox: Yup.bool().oneOf([true], "Hộp kiểm là bắt buộc"), radio: Yup.string().required("Radio là bắt buộc!"),});const onSubmit = (giá trị) => { alert(JSON.stringify(giá trị));};const App = () => { const { lỗi, đăng ký, xử lýSubmit } = useForm({ trình giải quyết: yupResolver(validationSchema), }); trả về (   //trường email  Email  {errors.email && 
 {errors.email.message} 
}  //chọn trường  Chọn màu để tiếp tục       {errors.select && 
 {errors.select.message} 
}  //checkbox field    Chấp nhận Điều khoản & Điều kiện  {errors.checkbox && ( 
 {errors.checkbox.message} 
 )}  //trường radio    Một    Hai  {errors.radio && 
 {errors.radio.message} 
}  Đăng nhập   );};
RHF hỗ trợ Yup và các sơ đồ xác thực khác. Để sử dụng Yup với RHF, chúng ta cần cài đặt gói @hookform/resolvers.
Mã:
npm i @hookform/resolvers
Tiếp theo, chúng ta phải cấu hình thiết lập RHF và hướng dẫn nó sử dụng Yup làm trình xác thực biểu mẫu. Chúng ta thực hiện điều này thông qua đối tượng cấu hình của hook useForm thuộc tính resolver. Chúng ta truyền vào yupResolver và bây giờ RHF biết cách sử dụng Yup để xác thực biểu mẫu.

Móc useForm cho phép chúng ta truy cập vào một số phương thức và thuộc tính biểu mẫu như đối tượng errors và các phương thức handleSubmitregister. Có những phương thức khác mà chúng ta có thể trích xuất từ useForm. Bạn có thể tìm thấy danh sách đầy đủ các phương thức.

Hàm register kết nối các trường nhập liệu với RHF thông qua thuộc tính ref của trường nhập liệu. Chúng ta truyền hàm register dưới dạng ref vào từng phần tử mà chúng ta muốn RHF theo dõi. Cách tiếp cận này giúp biểu mẫu hoạt động hiệu quả hơn và tránh việc hiển thị lại không cần thiết.

Phương thức handleSubmit xử lý việc gửi biểu mẫu. Phương thức này sẽ chỉ chạy nếu không có lỗi nào trong biểu mẫu.

Đối tượng errors chứa các lỗi có trong từng trường.

Sử dụng với các thành phần tùy chỉnh​

RHF giúp dễ dàng tích hợp với các thư viện thành phần UI bên ngoài. Khi sử dụng các thành phần tùy chỉnh, hãy kiểm tra xem thành phần bạn muốn sử dụng có hiển thị ref không. Nếu có, bạn có thể sử dụng nó như bạn sử dụng các thành phần biểu mẫu HTML gốc. Tuy nhiên, nếu không, bạn sẽ cần sử dụng thành phần Controller của RHF.

Material-UI và TextField của Reactstrap hiển thị inputRef của chúng, để bạn có thể truyền register vào đó.
Mã:
nhập TextField từ "@material-ui/core/TextField";export default function SignIn() { return (     Sign In    );}
Trong trường hợp inputRef của thành phần tùy chỉnh không được hiển thị, chúng ta phải sử dụng thành phần Controller của RHF.
Mã:
import { useForm, Controller } from "react-hook-form";import FormControlLabel from "@material-ui/core/FormControlLabel";import Checkbox from "@material-ui/core/Checkbox";export default function SignIn() { const { control } = useForm() return (     )} /> } label="Remember me" />  Đăng nhập     );}
Chúng tôi nhập thành phần Controller từ RHF và truy cập đối tượng control từ hook useForm.

Controller hoạt động như một wrapper cho phép chúng tôi sử dụng các thành phần tùy chỉnh trong RHF. Bất kỳ prop nào được truyền vào Controller sẽ được truyền xuống Checkbox.

Hàm prop render trả về một phần tử React và cung cấp khả năng đính kèm các sự kiện và giá trị vào thành phần. Điều này giúp đơn giản hóa việc tích hợp RHF với các thành phần tùy chỉnh. render cung cấp onChange, onBlur, name, refvalue cho thành phần tùy chỉnh.

Trường phụ thuộc​

Trong một số trường hợp, bạn có thể muốn hiển thị trường biểu mẫu phụ dựa trên giá trị mà người dùng đặt vào trường biểu mẫu chính. RHF cung cấp watch API cho phép chúng ta theo dõi giá trị của trường nhập liệu.
Mã:
export default function SignIn() { const { watch } = useForm() const terms = watch("remember"); return (    //các trường khác ở trên {terms && 
Cảm ơn bạn đã chấp nhận các điều khoản của chúng tôi. Bây giờ bạn có thể gửi biểu mẫu
}  Đăng nhập     );}

Learning Curve​

Ngoài tài liệu chi tiết và dễ hiểu bao gồm nhiều trường hợp sử dụng, RHF là một Thư viện React rất phổ biến. Điều này có nghĩa là có một số tài nguyên học tập giúp bạn bắt đầu và chạy.

Kích thước gói​

RHF có dung lượng 26,4kb đã thu nhỏ và 9,1kb đã nén.


Final Form​

Final Form là thư viện biểu mẫu không phụ thuộc vào khuôn khổ. Tuy nhiên, người sáng tạo ra nó, Erik Rasmussen, đã tạo ra một trình bao bọc React cho Final Form, React Final Form.

Cài đặt​

Mã:
npm i final-form react-final-formyarn add final-form react-final-form

Triển khai​

Không giống như Formik và React Hook Form, React Final Form (RFF) không hỗ trợ xác thực bằng Object Schema như Yup ngay khi xuất xưởng. Điều này có nghĩa là bạn phải tự thiết lập xác thực.
Xem thêm tại đây
Mã:
nhập { Biểu mẫu, Trường } từ "react-final-form";xuất khẩu mặc định hàm App() { trả về (   React Final Form   (  //trường email [TR] {({ input, meta }) => (  Email   )}  //select trường  {({ input, meta }) => (  Chọn màu để tiếp tục        )}  //hộp kiểm trường  {({ input, meta }) => (    Chấp nhận Điều khoản & Điều kiện   )}  //trường radio 2 [TR] {({ input, meta }) => (   Một    )}   {({ đầu vào, meta }) => (   Hai    )}    Đăng nhập   )} />  );}
Thành phần Form là một wrapper đặc biệt do RFF cung cấp để quản lý trạng thái của form. Các props chính khi sử dụng RFF là onSubmit, validaterender. Bạn có thể tìm hiểu thêm thông tin chi tiết về props form mà RFF sử dụng.

Chúng ta bắt đầu bằng cách thiết lập các trường nhập liệu cần thiết. render xử lý việc hiển thị form. Thông qua các props render, chúng ta có thể truy cập vào đối tượng FormState. Nó chứa các phương thức biểu mẫu như handleSubmit và các thuộc tính hữu ích khác liên quan đến trạng thái của biểu mẫu.

Giống như Formik, RFF có thành phần Field riêng để hiển thị các trường nhập. Thành phần Field đăng ký bất kỳ trường nhập nào trong đó, đăng ký trạng thái của trường nhập và đưa cả trạng thái trường và hàm gọi lại, onBlur, onChangeonFocus thông qua một render prop.

Không giống như Formik và RHF, RFF không cung cấp hỗ trợ cho bất kỳ Sơ đồ xác thực nào, vì vậy chúng ta phải thiết lập các quy tắc xác thực tùy chỉnh.
Mã:
const onSubmit = (giá trị) => { alert(JSON.stringify(giá trị));};const validate = (giá trị) => { const errors = {}; if (!values.email) { errors.email = "Yêu cầu nhập email"; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(giá trị.email)) { errors.email = "Địa chỉ email không hợp lệ"; } if (!values.checkbox) { errors.checkbox = "Bạn phải chấp nhận các điều khoản của chúng tôi"; } if (!values.select) { errors.select = "Yêu cầu chọn"; } if (!values.radio) { errors.radio = "Bạn phải chấp nhận các điều khoản của chúng tôi"; } return errors;};xuất khẩu mặc định hàm App() { trả về (   (   {({ input, meta }) => (  Email  {meta.error && meta.touched && ( {meta.error} )}  )}   {({ input, meta }) => (  Chọn màu để tiếp tục       {meta.error && meta.touched && (  {meta.error}  )}  )}   {({ input, meta }) => (    Chấp nhận Điều khoản & Điều kiện  {meta.error && meta.touched && ( {meta.error} )}  )}    {({ đầu vào, meta }) => (   Một    )}   {({ đầu vào, meta }) => (   Hai   {meta.error && meta.touched && ( {meta.error} )}  )}    Đăng nhập   )} />  );}
Hàm validate xử lý việc xác thực cho biểu mẫu. Hàm onSubmit sẽ được gọi với các giá trị của biểu mẫu khi người dùng gửi biểu mẫu và tất cả các xác thực đều vượt qua. Xác thực chạy khi đầu vào thay đổi theo mặc định. Tuy nhiên, chúng ta cũng có thể truyền validateonBlur prop cho thành phần xác thực Form để nó cũng chạy khi mờ.

Để hiển thị lỗi xác thực, chúng ta sử dụng đối tượng meta. Chúng ta có thể truy cập vào siêu dữ liệu và trạng thái của từng trường đầu vào thông qua đối tượng meta. Chúng ta có thể tìm hiểu xem biểu mẫu đã được chạm vào hay có bất kỳ lỗi nào thông qua các thuộc tính touchederror của meta tương ứng. Siêu dữ liệu này là một phần của props của Field thành phần. Nếu các trường nhập đã bị chạm vào và có lỗi, chúng tôi sẽ hiển thị lỗi đó.

Sử dụng với các thành phần tùy chỉnh​

Làm việc với các thành phần nhập tùy chỉnh trong RFF rất đơn giản. Sử dụng phương thức render props trong thành phần Field, chúng ta có thể truy cập inputmeta của mỗi trường đầu vào.
Mã:
const onSubmit = (giá trị) => {...};const validate = (giá trị) => {...};xuất khẩu mặc định hàm App() { trả về (  (  [TR] {({ đầu vào, meta }) => (  [TR] {meta.error && meta.touched && {meta.error}}  )}   Đăng nhập   )} > ); }}
Thành phần Field của RFF đóng gói tất cả các prop mà thành phần input của bạn cần vào một prop đối tượng, được gọi là input, chứa name, onBlur, onChange, onFocusvalue. Prop input là prop mà chúng ta truyền đến thành phần TextField. Thành phần biểu mẫu tùy chỉnh mà bạn định sử dụng phải hỗ trợ các prop này để tương thích với RFF.

Ngoài ra, chúng ta có thể hiển thị TextField của Material UI bằng thành phần Field trong RFF. Tuy nhiên, chúng ta sẽ không thể truy cập dữ liệu inputmeta bằng phương pháp này.
Mã:
///các nội dung biểu mẫu khác ở trên//chúng ta sẽ không thể truy cập dữ liệu đầu vào//và siêu dữ liệu bằng phương pháp này.///các nội dung biểu mẫu khác ở dưới

Các trường phụ thuộc​

Có thể truy cập đối tượng values từ render prop. Từ đây, chúng ta có thể theo dõi trạng thái của trường remember và nếu true, hiển thị thông báo hoặc bất kỳ trường hợp sử dụng nào phù hợp với nhu cầu của ứng dụng.
Mã:
 (   {({ input }) = > (  Remember me   )}  {values.remember && ( 
Cảm ơn bạn đã chấp nhận các điều khoản của chúng tôi. Bây giờ bạn có thể gửi biểu mẫu.
 )}  Submit  )} />

Đường cong học tập​

So sánh với các biểu mẫu khác thư viện, RFF không có nhiều tài nguyên học tập. Ngoài ra, tài liệu không đi sâu vào chi tiết để chỉ cách RFF có thể được sử dụng với Yup hoặc bất kỳ lược đồ xác thực nào khác và đó sẽ là một bổ sung hữu ích.

Kích thước gói​

RFF là 8,9kb đã thu nhỏ và 3,2kb đã nén.


Unform​

Một khía cạnh cốt lõi trong thiết kế API của Unform là cách dễ dàng để kết nối các đầu vào biểu mẫu với Unform. Ban đầu, Unform đi kèm với các thành phần đầu vào tích hợp, tuy nhiên, nó không còn theo mẫu đó nữa. Điều này có nghĩa là bạn phải đăng ký từng trường mà bạn muốn Unform theo dõi. Chúng ta có thể thực hiện điều đó bằng phương thức registerField mà Unform cung cấp.
Xem thêm tại đây

Cài đặt​

Mã:
npm i @unform/web @unform/coreyarn add @unform/web @unform/core

Triển khai​

Bước đầu tiên khi sử dụng Unform là đăng ký các trường nhập liệu mà chúng ta muốn thư viện theo dõi.

Móc useField là cốt lõi của Unform. Từ hook này, chúng ta có thể truy cập vào fieldName, defaultValue, registerField, error và nhiều hơn nữa. Hãy cùng xem chúng làm gì và hoạt động như thế nào.
Mã:
import { useEffect, useRef } từ "react";import { useField } từ "@unform/core";const Input = ({ name, label, ...rest }) => { const inputRef = useRef(); const { fieldName, defaultValue, registerField, error, clearError } = useField(name); useEffect(() => { registerField({ name: fieldName, ref: inputRef.current, getValue: (ref) => { return ref.value; } }); }, [fieldName, registerField]); return (  {label}  {error && {error}}  );};export default Input;
  • fieldName: tên trường duy nhất.
  • defaultValue: giá trị mặc định của trường.
  • registerField: phương thức này được sử dụng để đăng ký một trường trên Unform. Khi đăng ký một trường, bạn có thể truyền một số thuộc tính cho phương thức registerField.
  • error: thông báo lỗi của trường nhập đã đăng ký.
Bất cứ khi nào thành phần nhập được tải, chúng ta gọi phương thức registerField trong useEffect để đăng ký đầu vào. registerField chấp nhận một số tùy chọn:
  • name: tên của trường cần được đăng ký.
  • ref: tham chiếu đến trường.
  • getValue: hàm này trả về giá trị của trường.
Chúng ta truyền các phương thức; fieldName, defaultValue, clearError và bất kỳ thuộc tính nào khác cho thành phần nhập. clearError xóa lỗi của trường nhập khi được lấy nét nếu có. Đây là cách chúng ta đăng ký các trường nhập liệu với Unform. Chúng ta làm tương tự với các trường nhập liệu select, checkbox và radio.

Bây giờ chúng ta đã đăng ký các trường nhập liệu, chúng ta phải kết hợp mọi thứ lại với nhau.
Mã:
import React, { useRef } from "react";import { Form } from "@unform/web";import * as Yup from "yup";import Input from "./Input";import Radio from "./Radio";import Checkbox from "./Checkbox";import Select from "./Select";const radioOptions = [ { value: "option 1", label: "One" }, { value: "option 2", label: "Two" }];const selectOptions = [ { giá trị: "", nhãn: "Chọn màu" }, { giá trị: "đỏ", nhãn: "Đỏ" }, { giá trị: "xanh lam", nhãn: "Xanh lam" }, { giá trị: "xanh lá cây", nhãn: "Xanh lục" }];const App = () => { const formRef = useRef(); hàm async handleSubmit(data) { //xác thực biểu mẫu ở đây } return (                Đăng nhập    );};export default App;
Chúng tôi nhập thành phần Form từ Unform và thiết lập tham chiếu biểu mẫu cho thành phần Form. Chúng tôi có quyền truy cập vào một số phương pháp hữu ích từ tham chiếu này.

Bây giờ chúng tôi đã đăng ký các trường nhập, tạo tham chiếu biểu mẫu và thiết lập biểu mẫu, bước tiếp theo là xử lý xác thực và gửi biểu mẫu.
Mã:
import React, { useRef } from "react";const validationSchema = Yup.object().shape({ select: Yup.string().required("Màu là bắt buộc!"), email: Yup.string().email().required("Email là bắt buộc"), checkbox: Yup.bool().oneOf([true], "Hộp kiểm là bắt buộc"), radio: Yup.string().required("Radio là bắt buộc!")});const App = () => { const formRef = useRef(); hàm async handleSubmit(data) { try { await validationSchema.validate(data, { abortEarly: false }); // Xác thực đã vượt qua - thực hiện một số thao tác với dữ liệu alert(JSON.stringify(data)); } catch (err) { const errors = {}; // Xác thực không thành công - thực hiện hiển thị lỗi err.inner.forEach((error) => { errors[error.path] = error.message; }); formRef.current.setErrors(errors); } } return (   //các thành phần biểu mẫu khác bên dưới}
Unform hỗ trợ xác thực với Yup, vì vậy chúng ta tạo một schema. Theo mặc định, phương thức validate() của lược đồ sẽ từ chối lời hứa ngay khi tìm thấy lỗi và sẽ không xác thực bất kỳ trường nào nữa. Vì vậy, để tránh điều đó, bạn cần truyền tùy chọn abortEarly và đặt boolean thành false { abortEarly: false }. Chúng ta sử dụng phương thức setErrors từ tham chiếu biểu mẫu mà chúng ta đã tạo để đặt lỗi cho biểu mẫu nếu có.

Tương tự như hàm handleSubmit xử lý xác thực gửi, có thể tạo một hàm handleChange sẽ xử lý xác thực biểu mẫu khi người dùng nhập.
Mã:
import { useRef, useState } from "react";export default function App() { const [form, setForm] = useState({ name: "" }); const formRef = useRef(null); async function handleSubmit(data) { //handleSubmit logic } const handleNameChange = async ({ target: { value } }) => { setForm({ ...form, name: value }); try { formRef.current.setErrors({}); let schema = Yup.object().shape({ name: Yup.string() .required() .max(20) .matches( /^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$/, "Vui lòng nhập tên hợp lệ" ) }); await schema.validate(form, { abortEarly: false }); console.log(form); } catch (err) { console.log(err); const validationErrors = {}; if (err instanceof Yup.ValidationError) { err.inner.forEach((error) = > { validationErrors[error.path] = error.message; }); formRef.current.setErrors(validationErrors); } } }; return (       Lưu    );}
Cả hai hàm xác thực đều hoạt động theo cùng một cách, do đó logic cho xác thực submit và onChange là giống nhau. Tuy nhiên, có một số điểm khác biệt. Không giống như xác thực khi submit, nơi chúng ta có thể truy cập và xác thực dữ liệu biểu mẫu bằng handleSubmit, chúng ta cần một cách để xử lý dữ liệu đầu vào trong handleNameChange. Để thực hiện điều đó, chúng ta thiết lập trạng thái biểu mẫu nơi chúng ta sẽ lưu trữ giá trị đầu vào. Sau đó, khi người dùng nhập, chúng ta cập nhật trạng thái biểu mẫu thông qua setForm. Bây giờ chúng ta đã có quyền truy cập vào dữ liệu biểu mẫu, chúng ta xác thực dữ liệu theo cùng cách chúng ta đã làm trong handleSubmit. Cuối cùng, chúng ta phải truyền handleNameChange cho prop onChange của đầu vào, chúng ta thực hiện điều đó.

Bạn sẽ lưu ý rằng trong handleNameChange, tôi đã tạo một lược đồ xác thực khác với lược đồ tôi đã sử dụng trong handleSubmit. Tôi đã làm điều này để có hai lỗi khác nhau khiến lỗi onChangeonSubmit khác nhau. Tuy nhiên, trong một dự án thực tế, bạn sẽ sử dụng cùng một lược đồ xác thực.

Hộp cát bên dưới cung cấp bản demo để xác thực khi thay đổi đầu vào.
Xem thêm tại đây

Sử dụng với các thành phần tùy chỉnh​

Chúng tôi tích hợp các thành phần UI của bên thứ ba với Unform theo cùng cách chúng tôi làm với các đầu vào HTML gốc, thông qua phương thức registerField.
Mã:
import TextField from "@material-ui/core/TextField";const MaterialUIInput = ({ name, label, ...rest }) => { const inputRef = useRef(); const { fieldName, defaultValue, registerField, error } = useField(name); useEffect(() => { //đăng ký biểu mẫu tại đây }, [fieldName, registerField]); return (

Dependent Fields​

Unform hiện không cung cấp bất kỳ chức năng theo dõi nào để hỗ trợ tạo các trường phụ thuộc. Tuy nhiên, có các kế hoạch trong lộ trình của thư viện để tạo một móc useWatch để theo dõi trạng thái biểu mẫu.

Learning Curve​

Unform không phải là thư viện dễ bắt đầu nhất. Quá trình đăng ký các trường nhập liệu không thân thiện với nhà phát triển so với các bài viết khác. Ngoài ra, xác thực và truy cập Đối tượng errors trong Unform phức tạp hơn mức cần thiết. Cũng không có cách nào để truy cập các giá trị biểu mẫu để thiết lập các trường phụ thuộc. Nó không đi kèm nhiều tính năng cần thiết khi làm việc với biểu mẫu và có rất ít tài nguyên ngoài kia cho thấy các trường hợp sử dụng khác nhau khi sử dụng Unform. Tuy nhiên, tài liệu cung cấp một số ví dụ.

Nhìn chung, đây không phải là thư viện dễ sử dụng nhất. Tôi tin rằng có thể làm nhiều việc hơn để cung cấp tài liệu tốt hơn.

Với những điều đã nói, Unform vẫn đang trong quá trình phát triển và nhóm hiện đang làm việc trên các tính năng mới.

Kích thước gói​

Unform có dung lượng 10,4kb đã thu nhỏ và 3,7kb đã nén.


Tạo biểu mẫu nhiều bước​

Tôi đã tạo bản demo biểu mẫu nhiều bước cho từng thư viện. Tôi để phần này đến phần cuối vì cách triển khai cho các thư viện vẫn tương tự nhau. Điểm khác biệt duy nhất là giao diện người dùng biểu mẫu nhiều bước. Hãy cùng xem cấu trúc của UI.

Phân tích Trình hướng dẫn biểu mẫu​

Đối với trình hướng dẫn nhiều bước, hãy cùng xem cấu trúc tệp và cách thức hoạt động của nó.
Mã:
├── components| ├── FormCard.js| ├── FormCompleted.js| └── Forms| ├── BillingInfo.js| ├── ConfirmPurchase.js| ├── index.js| └── PersonalInfo.js├── context| └── index.js├── pages| ├── api| | └── hello.js| ├── index.js| └── _app.js└── styles ├── globals.css └── styles.module.scss
Chúng ta hãy xem tệp App.js.
Mã:
const App = () => { const [formStep, setFormStep] = useState(0); const nextFormStep = () => setFormStep((currentStep) => currentStep + 1); const prevFormStep = () => setFormStep((currentStep) => currentStep - 1); trả về (   Next.js Multi Step Form  [HEADING=1]Formik Multi Step Form[/HEADING]  {formStep >= 0 && ( 
 )} {formStep >= 1 && (  )} {formStep >= 2 && (  )} {formStep > 2 && }   );};
Tại đây, chúng ta định nghĩa trạng thái formStep, trạng thái này giữ trạng thái của bước hiện tại của trình hướng dẫn biểu mẫu. Chúng ta cũng định nghĩa các hàm prevFormStepnextFormStep để chuyển qua lại trong trình hướng dẫn biểu mẫu.

Tiếp theo, chúng ta truyền trạng thái formStep prevFormStep cho FormCard. Điều này sẽ cho phép chúng ta quay lại một bước và cũng hiển thị bước hiện tại của biểu mẫu.

Cuối cùng, chúng ta truyền formStepnextFormStep cho các thành phần biểu mẫu. Chúng tôi render có điều kiện từng form dựa trên giá trị của formStep. Chúng tôi sử dụng >= để render các form vì chúng tôi muốn các form vẫn được render ngay cả khi bước của nó đã được vượt qua. Điều này giúp theo dõi các giá trị form dễ dàng hơn.

Bây giờ là thành phần FormCard. Đây là vùng chứa cho mỗi biểu mẫu.
Mã:
export default function FormCard({ children, currentStep, prevFormStep }) { return (  {currentStep < 3 && (  {currentStep > 0 && (  back  )} Step {currentStep + 1} trong số 3  )} {children}  );}
FormCard thực hiện 3 việc: render nút quay lại có điều kiện dựa trên giá trị của formStep, hiển thị giá trị của bước hiện tại cho người dùng dưới dạng trình theo dõi tiến trình và render các thành phần con của nó, tức là form hiện tại đang được hiển thị.

Các thành phần form có cấu trúc tương tự nhau. Hãy cùng xem PersonalInfo.
Mã:
nhập { useFormData } từ "../../context";xuất mặc định hàm PersonalInfo({ formStep, nextFormStep }) { const { setFormValues } = useFormData(); const handleSubmit = (giá trị) => { setFormValues(giá trị); nextFormStep(); }; return (  [HEADING=2]Thông tin cá nhân[/HEADING]   Email    Tiếp theo    );}
Trong div gốc, chúng tôi áp dụng có điều kiện các kiểu showFormhideForm để hiển thị hoặc ẩn biểu mẫu. Chúng tôi thực hiện điều này vì cách chúng tôi triển khai trình hướng dẫn biểu mẫu.
Mã:
 {formStep >= 0 && ( 
 )} //các biểu mẫu khác bên dưới
Chúng tôi hiển thị một biểu mẫu cụ thể dựa trên giá trị của formStep. Tuy nhiên, chúng tôi sử dụng điều kiện >= để hiển thị biểu mẫu có điều kiện. Điều này có nghĩa là tất cả các biểu mẫu sẽ hiển thị khi formStep tăng lên. Chúng tôi muốn chúng hiển thị, nhưng cũng ẩn. Đó là lý do tại sao chúng ta áp dụng có điều kiện các kiểu showFormhideForm.

Cuối cùng, chúng ta có handleSumbit. Hãy cùng xem cách thức hoạt động của nó.

Xử lý việc gửi biểu mẫu bắt đầu bằng việc tạo ngữ cảnh để lưu trữ các giá trị của biểu mẫu.
Mã:
import { useState, createContext, useContext } from "react";export const FormContext = createContext();export default function FormProvider({ children }) { const [data, setData] = useState({}); const setFormValues = (values) => { setData((prevValues) => ({ ...prevValues, ...values, })); }; return (  {children}  );}export const useFormData = () => useContext(FormContext);
setFormValues là một hàm lấy dữ liệu từ mỗi biểu mẫu và sử dụng các giá trị đó để cập nhật trạng thái của data, trạng thái này sẽ giữ các giá trị của mỗi biểu mẫu.

Chúng ta có thể truy cập dữ liệu biểu mẫu và hàm setFormValues từ useFormData.
Mã:
import { useFormData } from "../../context";export default function PersonalInfo({ formStep, nextFormStep }) { const { setFormValues } = useFormData(); const handleSubmit = (values) => { setFormValues(values); nextFormStep(); };
Trong mỗi biểu mẫu, chúng tôi lấy setFormValues từ useFormData và truyền vào các giá trị của biểu mẫu. Theo cách này, khi chúng tôi gửi từng biểu mẫu, dữ liệu sẽ được lưu trữ.

Cuối cùng, nếu biểu mẫu đã được điền thành công, thành phần FormCompleted sẽ được hiển thị.
Mã:
export default function FormCompleted() { return [HEADING=2]Cảm ơn bạn đã mua hàng! 🎉[/HEADING];}
Điểm cốt lõi của việc tạo biểu mẫu nhiều bước là trình hướng dẫn. Xác thực biểu mẫu và gửi cho mỗi thư viện giống như những gì chúng tôi đã đề cập ở trên. Tôi đã đính kèm các bản demo hộp cát này để tích hợp với từng thư viện.
Xem thêm tại đâyXem thêm tại đâyXem thêm tại đâyXem thêm tại đâyXem thêm tại đây

Tóm tắt​

Khi so sánh 4 thư viện biểu mẫu này, chúng tôi đã xem xét các yếu tố khác nhau. Hình ảnh bên dưới là bảng biểu diễn về cách các thư viện này so sánh với nhau.



Tôi sử dụng Formik hoặc RHF để xử lý biểu mẫu trong các dự án của mình. Đây là những lựa chọn hàng đầu của tôi vì chúng phổ biến nhất, có tài liệu hướng dẫn rõ ràng và toàn diện nhất, và có nhiều tài nguyên học tập nhất về video và bài viết trên YouTube.

Kết luận​

Biểu mẫu sẽ vẫn là một phần quan trọng trong cách người dùng tương tác với web và các thư viện này, cùng với những thư viện khác, đã làm tốt trong việc tạo ra các giải pháp quản lý biểu mẫu cho các trường hợp sử dụng phổ biến của nhà phát triển và hơn thế nữa.

Tài nguyên​

 
Back
Bên trên