สำรวจพลังของ React's useFormState hook เพื่อการจัดการสถานะฟอร์มที่คล่องตัว เรียนรู้วิธีสร้างฟอร์มที่แข็งแกร่งและใช้งานง่ายได้อย่างง่ายดาย
React useFormState: คู่มือฉบับสมบูรณ์เพื่อการจัดการสถานะฟอร์ม
แบบฟอร์มเป็นส่วนพื้นฐานของเกือบทุกเว็บแอปพลิเคชัน ช่วยให้ผู้ใช้โต้ตอบกับแอปพลิเคชัน ส่งข้อมูล และดำเนินการต่างๆ การจัดการสถานะฟอร์มอย่างมีประสิทธิภาพเป็นสิ่งสำคัญสำหรับการสร้างฟอร์มที่แข็งแกร่งและใช้งานง่าย React's useFormState hook นำเสนอโซลูชันที่ทรงพลังและสวยงามสำหรับการลดความซับซ้อนในการจัดการสถานะฟอร์ม
useFormState คืออะไร?
useFormState คือ React hook ที่ช่วยลดความซับซ้อนในการจัดการสถานะฟอร์มโดยการจัดหาสถานที่ส่วนกลางสำหรับจัดเก็บและอัปเดตค่าฟอร์ม ติดตามการเปลี่ยนแปลงอินพุต จัดการการตรวจสอบ และจัดการสถานะการส่ง ช่วยให้กระบวนการสร้างฟอร์มที่ซับซ้อนง่ายขึ้นโดยการลดโค้ดสำเร็จรูปและปรับปรุงความสามารถในการอ่านโค้ด
เมื่อเทียบกับแนวทางดั้งเดิมที่ใช้ useState สำหรับแต่ละฟิลด์ฟอร์ม useFormState มีข้อดีหลายประการ:
- สถานะส่วนกลาง: จัดการข้อมูลฟอร์มทั้งหมดในออบเจ็กต์สถานะเดียว ปรับปรุงองค์กรและลดความซับซ้อน
- การอัปเดตที่ง่ายขึ้น: จัดหาวิธีที่สะดวกในการอัปเดตฟิลด์ฟอร์มหลายฟิลด์พร้อมกัน
- การตรวจสอบในตัว: นำเสนอการสนับสนุนในตัวสำหรับการตรวจสอบฟอร์ม ช่วยให้คุณตรวจสอบข้อมูลฟอร์มและแสดงข้อความแสดงข้อผิดพลาดได้อย่างง่ายดาย
- การจัดการการส่ง: จัดหากลไกสำหรับการจัดการสถานะการส่งฟอร์ม เช่น การติดตามว่าฟอร์มกำลังส่งอยู่หรือไม่ หรือส่งไปแล้ว
- ปรับปรุงความสามารถในการอ่าน: ลดความซับซ้อนของตรรกะฟอร์ม ทำให้ง่ายต่อการทำความเข้าใจและบำรุงรักษา
การใช้งานพื้นฐาน
มาเริ่มต้นด้วยตัวอย่างพื้นฐานของวิธีการใช้ useFormState ในฟอร์มง่ายๆ ที่มีสองฟิลด์อินพุต: ชื่อและอีเมล
การติดตั้ง
ขั้นแรก คุณจะต้องติดตั้ง useFormState hook วิธีการติดตั้งจะขึ้นอยู่กับไลบรารีหรือเฟรมเวิร์กที่คุณใช้ซึ่งมี hook ให้ (เช่น React Hook Form, Formik พร้อม custom hook หรือโซลูชันที่คล้ายกัน) ตัวอย่างนี้ใช้ไลบรารีสมมติชื่อ react-form-state (แทนที่ด้วยไลบรารีจริงของคุณ):
npm install react-form-state
ตัวอย่างโค้ด
import React from 'react';
import { useFormState } from 'react-form-state';
function MyForm() {
const { values, errors, touched, handleChange, handleSubmit, isSubmitting } = useFormState({
initialValues: {
name: '',
email: '',
},
onSubmit: async (values) => {
// Simulate an API call
await new Promise((resolve) => setTimeout(resolve, 1000));
alert(JSON.stringify(values));
},
validate: (values) => {
const errors = {};
if (!values.name) {
errors.name = 'Name is required';
}
if (!values.email) {
errors.email = 'Email is required';
} else if (!/^\w[\w.-]+@([\w-]+\.)+[\w-]{2,4}$/.test(values.email)) {
errors.email = 'Invalid email format';
}
return errors;
},
});
return (
);
}
export default MyForm;
คำอธิบาย
- นำเข้า
useFormState: เรานำเข้าuseFormStatehook จากไลบรารีreact-form-state - เริ่มต้น Hook: เราเรียก
useFormStateด้วยออบเจ็กต์ตัวเลือก ออบเจ็กต์นี้ประกอบด้วย: initialValues: ออบเจ็กต์ที่กำหนดค่าเริ่มต้นของฟิลด์ฟอร์มonSubmit: ฟังก์ชันที่ถูกเรียกเมื่อส่งฟอร์ม ฟังก์ชันนี้รับค่าฟอร์มเป็นอาร์กิวเมนต์ ในตัวอย่างนี้ เราจำลองการเรียก API ด้วยsetTimeoutvalidate: ฟังก์ชันที่ตรวจสอบค่าฟอร์ม ฟังก์ชันนี้ควรถือออบเจ็กต์ที่คีย์คือชื่อฟิลด์ และค่าคือข้อความแสดงข้อผิดพลาด หากฟิลด์ถูกต้อง ไม่ควรรวมอยู่ในออบเจ็กต์ที่ส่งคืน- Destructure Values: เรา destructure ค่าที่ส่งคืนของ
useFormStateเพื่อรับค่าต่อไปนี้: values: ออบเจ็กต์ที่มีค่าปัจจุบันของฟิลด์ฟอร์มerrors: ออบเจ็กต์ที่มีข้อผิดพลาดในการตรวจสอบใดๆtouched: ออบเจ็กต์ที่ระบุว่าฟิลด์ใดที่ถูกสัมผัส (เช่น ถูกโฟกัสแล้วเบลอ)handleChange: ฟังก์ชันที่อัปเดตค่าฟอร์มเมื่อฟิลด์อินพุตเปลี่ยนแปลงhandleSubmit: ฟังก์ชันที่จัดการการส่งฟอร์มisSubmitting: บูลีนที่ระบุว่าฟอร์มกำลังส่งอยู่หรือไม่- การเรนเดอร์ฟอร์ม: เราเรนเดอร์ฟอร์มด้วยฟิลด์อินพุต แต่ละฟิลด์อินพุตเชื่อมต่อกับออบเจ็กต์
valuesและฟังก์ชันhandleChange - การแสดงข้อผิดพลาด: เราแสดงข้อความแสดงข้อผิดพลาดสำหรับแต่ละฟิลด์ หากฟิลด์ถูกสัมผัสและมีข้อผิดพลาด
- ปุ่มส่ง: ปุ่มส่งถูกปิดใช้งานในขณะที่ฟอร์มกำลังส่ง
คุณสมบัติขั้นสูง
useFormState นำเสนอคุณสมบัติขั้นสูงที่หลากหลายเพื่อจัดการสถานการณ์ฟอร์มที่ซับซ้อนมากขึ้น
การตรวจสอบแบบกำหนดเอง
ฟังก์ชัน validate ช่วยให้คุณใช้ตรรกะการตรวจสอบแบบกำหนดเองได้ คุณสามารถดำเนินการตรวจสอบที่ซับซ้อน เช่น การตรวจสอบกับฐานข้อมูลหรือการใช้ regular expression ตัวอย่างเช่น การตรวจสอบหมายเลขโทรศัพท์ตามรหัสประเทศ:
const validate = (values) => {
const errors = {};
if (!values.phoneNumber) {
errors.phoneNumber = 'Phone number is required';
} else {
// Example: Validate US phone number format
if (values.countryCode === 'US' && !/^\d{3}-\d{3}-\d{4}$/.test(values.phoneNumber)) {
errors.phoneNumber = 'Invalid US phone number format (e.g., 123-456-7890)';
}
// Example: Validate UK phone number format
if (values.countryCode === 'UK' && !/^\d{5} \d{6}$/.test(values.phoneNumber)) {
errors.phoneNumber = 'Invalid UK phone number format (e.g., 01632 960001)';
}
// More country-specific validation can be added here
}
return errors;
};
การตรวจสอบแบบอะซิงโครนัส
สำหรับการตรวจสอบที่ต้องมีการดำเนินการแบบอะซิงโครนัส (เช่น การตรวจสอบว่ามีชื่อผู้ใช้หรือไม่) คุณสามารถใช้ฟังก์ชัน validate แบบอะซิงโครนัสได้
const validate = async (values) => {
const errors = {};
// Simulate an API call to check username availability
const isUsernameAvailable = await checkUsernameAvailability(values.username);
if (!isUsernameAvailable) {
errors.username = 'Username is already taken';
}
return errors;
};
async function checkUsernameAvailability(username) {
// Replace with your actual API call
await new Promise((resolve) => setTimeout(resolve, 500));
// Simulate username taken
return username !== 'taken_username';
}
ฟอร์มแบบไดนามิก
useFormState สามารถใช้เพื่อสร้างฟอร์มแบบไดนามิกที่ฟิลด์ฟอร์มถูกเพิ่มหรือลบตามการโต้ตอบของผู้ใช้ สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับฟอร์มที่มีจำนวนฟิลด์อินพุตที่เปลี่ยนแปลงได้
import React, { useState } from 'react';
import { useFormState } from 'react-form-state';
function DynamicForm() {
const [items, setItems] = useState(['item1']);
const { values, handleChange, handleSubmit } = useFormState({
initialValues: items.reduce((acc, item) => {
acc[item] = '';
return acc;
}, {}),
onSubmit: (values) => {
alert(JSON.stringify(values));
},
});
const addItem = () => {
const newItem = `item${items.length + 1}`;
setItems([...items, newItem]);
};
return (
);
}
export default DynamicForm;
การจัดการฟิลด์อาร์เรย์
เมื่อฟอร์มของคุณมีฟิลด์อาร์เรย์ (เช่น รายการงานอดิเรกหรือทักษะ) useFormState สามารถปรับให้เข้ากับการจัดการค่าอาร์เรย์เหล่านี้ได้อย่างมีประสิทธิภาพ นี่คือตัวอย่าง:
import React from 'react';
import { useFormState } from 'react-form-state';
function SkillsForm() {
const { values, handleChange, handleSubmit } = useFormState({
initialValues: {
skills: [''], // Start with one empty skill
},
onSubmit: (values) => {
alert(JSON.stringify(values));
},
});
const addSkill = () => {
handleChange({ target: { name: 'skills', value: [...values.skills, ''] } });
};
const updateSkill = (index, value) => {
const newSkills = [...values.skills];
newSkills[index] = value;
handleChange({ target: { name: 'skills', value: newSkills } });
};
return (
);
}
export default SkillsForm;
ข้อควรพิจารณาเกี่ยวกับการเข้าถึง
เมื่อสร้างฟอร์ม สิ่งสำคัญคือต้องพิจารณาถึงการเข้าถึงเพื่อให้แน่ใจว่าผู้ใช้ที่มีความพิการสามารถใช้ฟอร์มได้อย่างมีประสิทธิภาพ นี่คือเคล็ดลับการเข้าถึงบางส่วน:
- ใช้ semantic HTML: ใช้ HTML elements ที่เหมาะสม เช่น
<label>,<input>,<textarea>, และ<button> - จัดหาป้ายกำกับสำหรับทุกฟิลด์ฟอร์ม: ใช้
<label>element เพื่อเชื่อมโยงป้ายกำกับกับฟิลด์ฟอร์ม ตรวจสอบให้แน่ใจว่าforattribute ของป้ายกำกับตรงกับidattribute ของฟิลด์อินพุต - ใช้ ARIA attributes: ใช้ ARIA attributes เพื่อให้ข้อมูลเพิ่มเติมเกี่ยวกับฟิลด์ฟอร์มแก่ assistive technologies ตัวอย่างเช่น ใช้
aria-describedbyเพื่อเชื่อมโยงข้อความแสดงข้อผิดพลาดกับฟิลด์ฟอร์ม - ให้ข้อความแสดงข้อผิดพลาดที่ชัดเจนและกระชับ: ข้อความแสดงข้อผิดพลาดควรเข้าใจง่ายและให้คำแนะนำเกี่ยวกับวิธีการแก้ไขข้อผิดพลาด
- ตรวจสอบให้แน่ใจว่ามี color contrast เพียงพอ: ใช้ color contrast ที่เพียงพอระหว่างข้อความและสีพื้นหลังเพื่อให้ฟอร์มสามารถอ่านได้สำหรับผู้ใช้ที่มีความบกพร่องทางการมองเห็น
- ทดสอบด้วย assistive technologies: ทดสอบฟอร์มด้วย assistive technologies เช่น screen reader เพื่อให้แน่ใจว่าผู้ใช้ที่มีความพิการสามารถเข้าถึงได้
แนวทางปฏิบัติที่ดีที่สุด
นี่คือแนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ useFormState:
- ทำให้ฟังก์ชัน
validateบริสุทธิ์: ฟังก์ชันvalidateควรเป็นฟังก์ชันบริสุทธิ์ หมายความว่าจะต้องไม่มีผลข้างเคียงใดๆ และควรส่งคืนเอาต์พุตเดียวกันเสมอสำหรับอินพุตเดียวกัน - ใช้ memoization: ใช้ memoization เพื่อเพิ่มประสิทธิภาพของฟอร์ม Memoization สามารถช่วยป้องกันการเรนเดอร์ฟอร์มคอมโพเนนต์ที่ไม่จำเป็นซ้ำได้
- ใช้ naming convention ที่สอดคล้องกัน: ใช้ naming convention ที่สอดคล้องกันสำหรับฟิลด์ฟอร์มและข้อผิดพลาดในการตรวจสอบ สิ่งนี้จะทำให้โค้ดอ่านและบำรุงรักษาง่ายขึ้น
- เขียน unit test: เขียน unit test เพื่อให้แน่ใจว่าฟอร์มทำงานถูกต้อง Unit test สามารถช่วยตรวจจับข้อผิดพลาดได้ตั้งแต่เนิ่นๆ ในกระบวนการพัฒนา
- พิจารณา internationalization (i18n): สำหรับแอปพลิเคชันระดับโลก ตรวจสอบให้แน่ใจว่าป้ายกำกับ ข้อความ และกฎการตรวจสอบของฟอร์มของคุณรองรับหลายภาษา ไลบรารีเช่น
react-intlหรือi18nextสามารถช่วยในเรื่องนี้ได้
ตัวอย่างสากล
เมื่อทำงานกับฟอร์มในระดับโลก สิ่งสำคัญคือต้องพิจารณาถึง internationalization และ localization นี่คือตัวอย่างบางส่วนของวิธีการจัดการข้อกำหนดฟอร์มสากลที่แตกต่างกัน:
- หมายเลขโทรศัพท์: ประเทศต่างๆ มีรูปแบบหมายเลขโทรศัพท์ที่แตกต่างกัน ใช้ไลบรารีเช่น
libphonenumber-jsเพื่อตรวจสอบหมายเลขโทรศัพท์ตามรหัสประเทศ - รหัสไปรษณีย์: รหัสไปรษณีย์แตกต่างกันอย่างมากในแต่ละประเทศ บางประเทศใช้รหัสไปรษณีย์ที่เป็นตัวเลข ในขณะที่บางประเทศใช้รหัสที่เป็นตัวอักษรและตัวเลข ใช้ตรรกะการตรวจสอบที่รองรับรูปแบบรหัสไปรษณีย์ที่แตกต่างกัน
- รูปแบบวันที่: รูปแบบวันที่แตกต่างกันไปในแต่ละวัฒนธรรม บางประเทศใช้รูปแบบ MM/DD/YYYY ในขณะที่บางประเทศใช้รูปแบบ DD/MM/YYYY ใช้ไลบรารีเช่น
moment.jsหรือdate-fnsเพื่อจัดรูปแบบและแยกวิเคราะห์วันที่ตาม locale ของผู้ใช้ - รูปแบบที่อยู่: รูปแบบที่อยู่ก็แตกต่างกันไปในแต่ละประเทศเช่นกัน บางประเทศกำหนดให้ที่อยู่ถนนอยู่ในบรรทัดแรก ในขณะที่บางประเทศกำหนดให้เมืองและรหัสไปรษณีย์อยู่ในบรรทัดแรก ใช้ไลบรารีหรือ API เพื่อจัดรูปแบบที่อยู่ตามประเทศของผู้ใช้
- รูปแบบสกุลเงิน: แสดงค่าสกุลเงินในรูปแบบที่เหมาะสมสำหรับ locale ของผู้ใช้ ใช้
Intl.NumberFormatAPI เพื่อจัดรูปแบบค่าสกุลเงิน
ตัวอย่างเช่น พิจารณาแบบฟอร์มการลงทะเบียนที่ต้องเก็บหมายเลขโทรศัพท์ แทนที่จะใช้ฟิลด์ "หมายเลขโทรศัพท์" เดียว อาจเป็นประโยชน์ที่จะมีฟิลด์แยกต่างหากสำหรับ "รหัสประเทศ" และ "หมายเลขโทรศัพท์" รวมกับไลบรารีการตรวจสอบเพื่อปรับให้เข้ากับรูปแบบท้องถิ่นเฉพาะ
ทางเลือกอื่นสำหรับ useFormState
แม้ว่า useFormState จะนำเสนอโซลูชันที่สะดวกสำหรับการจัดการสถานะฟอร์ม แต่ก็มีไลบรารีและแนวทางยอดนิยมอื่นๆ ที่คุณสามารถพิจารณาได้:
- Formik: ไลบรารีที่ใช้กันอย่างแพร่หลายซึ่งมีคุณสมบัติการจัดการฟอร์มที่ครอบคลุม รวมถึงการจัดการสถานะ การตรวจสอบ และการจัดการการส่ง
- React Hook Form: ไลบรารีที่มีประสิทธิภาพซึ่งใช้ React's
useRefhook เพื่อลดการเรนเดอร์ซ้ำและปรับปรุงประสิทธิภาพของฟอร์ม - Redux Form: ไลบรารีที่ผสานรวมกับ Redux เพื่อจัดการสถานะฟอร์ม นี่เป็นตัวเลือกที่ดีหากคุณกำลังใช้ Redux ในแอปพลิเคชันของคุณอยู่แล้ว
- Custom Hooks: คุณสามารถสร้าง custom hook ของคุณเองเพื่อจัดการสถานะฟอร์มได้ สิ่งนี้ทำให้คุณมีความยืดหยุ่นมากที่สุด แต่ต้องใช้ความพยายามมากขึ้น
สรุป
React's useFormState hook นำเสนอโซลูชันที่ทรงพลังและสวยงามสำหรับการลดความซับซ้อนในการจัดการสถานะฟอร์ม โดยการรวมศูนย์สถานะ ลดความซับซ้อนในการอัปเดต จัดหาการตรวจสอบในตัว และจัดการสถานะการส่ง useFormState สามารถปรับปรุงประสบการณ์การพัฒนาและคุณภาพโค้ดของ React forms ของคุณได้อย่างมาก
ไม่ว่าคุณจะสร้างฟอร์มง่ายๆ หรือฟอร์มที่ซับซ้อนด้วยฟิลด์แบบไดนามิกและข้อกำหนด internationalization useFormState สามารถช่วยคุณสร้างฟอร์มที่แข็งแกร่ง เข้าถึงได้ และใช้งานง่ายได้อย่างง่ายดาย พิจารณาข้อกำหนดเฉพาะของโครงการของคุณและเลือกแนวทางที่เหมาะสมกับความต้องการของคุณมากที่สุด อย่าลืมจัดลำดับความสำคัญของการเข้าถึงและ internationalization เพื่อให้แน่ใจว่าทุกคนสามารถใช้ฟอร์มของคุณได้ โดยไม่คำนึงถึงความสามารถหรือสถานที่ตั้ง