ไทย

เจาะลึก useFormState hook ของ React เพื่อจัดการฟอร์มให้ง่ายขึ้น ปรับปรุงประสิทธิภาพ และยกระดับประสบการณ์ผู้ใช้ เรียนรู้แนวทางปฏิบัติที่ดีที่สุดและเทคนิคขั้นสูงสำหรับการสร้างฟอร์มที่แข็งแกร่งและมีประสิทธิภาพ

React useFormState: เชี่ยวชาญการจัดการฟอร์มเพื่อเพิ่มประสิทธิภาพประสบการณ์ผู้ใช้

ฟอร์มเป็นส่วนพื้นฐานของเว็บแอปพลิเคชัน ที่ช่วยให้ผู้ใช้สามารถโต้ตอบกับแอปพลิเคชันของคุณและส่งข้อมูลได้ อย่างไรก็ตาม การจัดการสถานะของฟอร์ม (form state) การตรวจสอบความถูกต้อง และการให้ผลตอบรับอาจมีความซับซ้อน โดยเฉพาะในแอปพลิเคชันขนาดใหญ่และมีการเปลี่ยนแปลงตลอดเวลา useFormState hook ของ React ซึ่งเปิดตัวใน React 18 นำเสนอวิธีที่มีประสิทธิภาพในการจัดการสถานะของฟอร์มและปรับปรุงตรรกะการจัดการฟอร์มให้ง่ายขึ้น ซึ่งนำไปสู่ประสิทธิภาพที่ดีขึ้นและประสบการณ์ผู้ใช้ที่ดียิ่งขึ้น คู่มือฉบับสมบูรณ์นี้จะสำรวจ useFormState hook อย่างลึกซึ้ง ครอบคลุมแนวคิดหลัก ประโยชน์ ตัวอย่างการใช้งานจริง และเทคนิคขั้นสูง

React useFormState คืออะไร?

useFormState คือ React hook ที่ช่วยลดความซับซ้อนในการจัดการสถานะของฟอร์มโดยการห่อหุ้มสถานะและตรรกะการอัปเดตไว้ภายใน hook เดียว มันถูกออกแบบมาโดยเฉพาะเพื่อทำงานร่วมกับ React Server Components และ Server Actions ทำให้สามารถทำ Progressive Enhancement และปรับปรุงประสิทธิภาพโดยการย้ายการประมวลผลฟอร์มไปที่เซิร์ฟเวอร์

คุณสมบัติและประโยชน์ที่สำคัญ:

ทำความเข้าใจ useFormState Hook

useFormState hook รับอาร์กิวเมนต์สองตัว:

  1. Server Action: ฟังก์ชันที่จะถูกเรียกใช้งานเมื่อฟอร์มถูกส่ง โดยทั่วไปฟังก์ชันนี้จะจัดการการตรวจสอบความถูกต้องของฟอร์ม การประมวลผลข้อมูล และการอัปเดตฐานข้อมูล
  2. สถานะเริ่มต้น (Initial State): ค่าเริ่มต้นของสถานะของฟอร์ม ซึ่งสามารถเป็นค่า JavaScript ใดก็ได้ เช่น object, array, หรือ primitive

hook นี้จะคืนค่ากลับมาเป็น array ที่มีสองค่า:

  1. สถานะของฟอร์ม (Form State): ค่าปัจจุบันของสถานะของฟอร์ม
  2. Form Action: ฟังก์ชันที่คุณส่งต่อไปยัง prop action ขององค์ประกอบ form ฟังก์ชันนี้จะเรียกใช้ server action เมื่อฟอร์มถูกส่ง

ตัวอย่างพื้นฐาน:

ลองพิจารณาตัวอย่างง่ายๆ ของฟอร์มติดต่อที่ให้ผู้ใช้ส่งชื่อและที่อยู่อีเมลของพวกเขา

// Server Action (ตัวอย่าง - ต้องถูกกำหนดไว้ที่อื่น)
async function submitContactForm(prevState, formData) {
  // ตรวจสอบข้อมูลฟอร์ม
  const name = formData.get('name');
  const email = formData.get('email');

  if (!name || !email) {
    return { message: 'กรุณากรอกข้อมูลในทุกช่อง' };
  }

  // ประมวลผลข้อมูลฟอร์ม (เช่น ส่งอีเมล)
  try {
    // จำลองการส่งอีเมล
    await new Promise(resolve => setTimeout(resolve, 1000)); // จำลองการทำงานแบบอะซิงโครนัส
    return { message: 'ขอบคุณสำหรับการส่งข้อมูลของคุณ!' };
  } catch (error) {
    return { message: 'เกิดข้อผิดพลาดขึ้น กรุณาลองอีกครั้งในภายหลัง' };
  }
}

// React Component
'use client'; // สำคัญสำหรับ Server Actions

import { useFormState } from 'react-dom';

function ContactForm() {
  const [state, formAction] = useFormState(submitContactForm, { message: null });

  return (
    




{state?.message &&

{state.message}

}
); } export default ContactForm;

ในตัวอย่างนี้ ฟังก์ชัน submitContactForm คือ server action มันรับสถานะก่อนหน้าและข้อมูลฟอร์มเป็นอาร์กิวเมนต์ มันจะตรวจสอบความถูกต้องของข้อมูลฟอร์ม และหากถูกต้อง ก็จะประมวลผลข้อมูลและคืนค่า object สถานะใหม่พร้อมข้อความแสดงความสำเร็จ หากมีข้อผิดพลาด มันจะคืนค่า object สถานะใหม่พร้อมข้อความแสดงข้อผิดพลาด useFormState hook จะจัดการสถานะของฟอร์มและให้ฟังก์ชัน formAction ซึ่งจะถูกส่งไปยัง prop action ขององค์ประกอบ form เมื่อฟอร์มถูกส่ง ฟังก์ชัน submitContactForm จะถูกเรียกใช้งานบนเซิร์ฟเวอร์ และสถานะผลลัพธ์จะถูกอัปเดตในคอมโพเนนต์

เทคนิค useFormState ขั้นสูง

1. การตรวจสอบความถูกต้องของฟอร์ม (Form Validation):

การตรวจสอบความถูกต้องของฟอร์มเป็นสิ่งสำคัญเพื่อให้แน่ใจในความสมบูรณ์ของข้อมูลและมอบประสบการณ์ที่ดีแก่ผู้ใช้ สามารถใช้ useFormState เพื่อจัดการตรรกะการตรวจสอบความถูกต้องของฟอร์มบนเซิร์ฟเวอร์ได้ นี่คือตัวอย่าง:

async function validateForm(prevState, formData) {
  const name = formData.get('name');
  const email = formData.get('email');

  let errors = {};

  if (!name) {
    errors.name = 'จำเป็นต้องกรอกชื่อ';
  }

  if (!email) {
    errors.email = 'จำเป็นต้องกรอกอีเมล';
  } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    errors.email = 'รูปแบบอีเมลไม่ถูกต้อง';
  }

  if (Object.keys(errors).length > 0) {
    return { errors: errors };
  }

  // ประมวลผลข้อมูลฟอร์ม (เช่น บันทึกลงฐานข้อมูล)
  return { message: 'ส่งฟอร์มสำเร็จ!', errors: null };
}

function MyForm() {
  const [state, action] = useFormState(validateForm, { message: null, errors: null });

  return (
    

{state?.errors?.name &&

{state.errors.name}

}
{state?.errors?.email &&

{state.errors.email}

} {state?.message &&

{state.message}

}
); }

ในตัวอย่างนี้ server action validateForm จะตรวจสอบความถูกต้องของข้อมูลฟอร์มและคืนค่า object ที่มีข้อผิดพลาดในการตรวจสอบใดๆ คอมโพเนนต์ก็จะแสดงข้อผิดพลาดเหล่านี้ให้ผู้ใช้เห็น

2. การอัปเดตเชิงบวก (Optimistic Updates):

การอัปเดตเชิงบวกสามารถปรับปรุงประสบการณ์ของผู้ใช้โดยการให้ผลตอบรับทันที แม้กระทั่งก่อนที่เซิร์ฟเวอร์จะประมวลผลการส่งฟอร์มเสร็จสิ้น ด้วย useFormState และตรรกะฝั่งไคลเอ็นต์เล็กน้อย คุณสามารถใช้การอัปเดตเชิงบวกโดยการอัปเดตสถานะของฟอร์มทันทีหลังจากส่งฟอร์ม แล้วย้อนกลับการอัปเดตหากเซิร์ฟเวอร์คืนค่าข้อผิดพลาดกลับมา

'use client'

import { useFormState } from 'react-dom';
import { useState } from 'react';

async function submitForm(prevState, formData) {
  await new Promise(resolve => setTimeout(resolve, 1000)); // จำลองความล่าช้าของเครือข่าย

  const value = formData.get('value');
  if (value === 'error') {
    return { message: 'การส่งล้มเหลว!' };
  }
  return { message: 'การส่งสำเร็จ!' };
}

function OptimisticForm() {
  const [optimisticValue, setOptimisticValue] = useState('');
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [state, action] = useFormState(submitForm, { message: '' });

  const handleSubmit = async (e) => {
    setIsSubmitting(true);
    setOptimisticValue(e.target.value.value);
    const formData = new FormData(e.target);
    const result = await action(prevState, formData);
    setIsSubmitting(false);

    if (result?.message === 'การส่งล้มเหลว!') {
      setOptimisticValue(''); // ย้อนกลับเมื่อเกิดข้อผิดพลาด
    }
  };

  return (
    


{state?.message &&

{state.message}

}
); }

ในตัวอย่างนี้ เรากำลังจำลองการตอบสนองของเซิร์ฟเวอร์ที่ล่าช้า ก่อนที่ server action จะเสร็จสมบูรณ์ ช่องป้อนข้อมูลจะถูกอัปเดตในเชิงบวกด้วยค่าที่ส่งไป หาก server action ล้มเหลว (จำลองโดยการส่งค่า 'error') ช่องป้อนข้อมูลจะถูกย้อนกลับไปยังสถานะก่อนหน้า

3. การจัดการการอัปโหลดไฟล์:

useFormState ยังสามารถใช้เพื่อจัดการการอัปโหลดไฟล์ได้อีกด้วย object FormData จะจัดการข้อมูลไฟล์โดยอัตโนมัติ นี่คือตัวอย่าง:

async function uploadFile(prevState, formData) {
  const file = formData.get('file');

  if (!file) {
    return { message: 'กรุณาเลือกไฟล์' };
  }

  // จำลองการอัปโหลดไฟล์
  await new Promise(resolve => setTimeout(resolve, 1000));

  // โดยปกติคุณจะอัปโหลดไฟล์ไปยังเซิร์ฟเวอร์ที่นี่
  console.log('ไฟล์ที่อัปโหลด:', file.name);

  return { message: `ไฟล์ ${file.name} อัปโหลดสำเร็จ!` };
}

function FileUploadForm() {
  const [state, action] = useFormState(uploadFile, { message: null });

  return (
    


{state?.message &&

{state.message}

}
); }

ในตัวอย่างนี้ server action uploadFile จะดึงไฟล์จาก object FormData และประมวลผล ในแอปพลิเคชันจริง โดยทั่วไปคุณจะอัปโหลดไฟล์ไปยังบริการจัดเก็บข้อมูลบนคลาวด์ เช่น Amazon S3 หรือ Google Cloud Storage

4. Progressive Enhancement:

หนึ่งในข้อได้เปรียบที่สำคัญของ useFormState และ Server Actions คือความสามารถในการให้ Progressive Enhancement ซึ่งหมายความว่าฟอร์มของคุณยังคงทำงานได้แม้ว่า JavaScript จะถูกปิดใช้งานในเบราว์เซอร์ของผู้ใช้ ฟอร์มจะส่งข้อมูลโดยตรงไปยังเซิร์ฟเวอร์ และ server action จะจัดการการส่งฟอร์ม เมื่อ JavaScript ถูกเปิดใช้งาน React จะปรับปรุงฟอร์มด้วยการโต้ตอบและการตรวจสอบฝั่งไคลเอ็นต์

เพื่อให้แน่ใจว่ามี Progressive Enhancement คุณควรตรวจสอบให้แน่ใจว่า server actions ของคุณจัดการตรรกะการตรวจสอบความถูกต้องของฟอร์มและการประมวลผลข้อมูลทั้งหมด คุณยังสามารถจัดเตรียมกลไกสำรองสำหรับผู้ใช้ที่ไม่มี JavaScript ได้อีกด้วย

5. ข้อควรพิจารณาด้านการเข้าถึงได้ (Accessibility):

เมื่อสร้างฟอร์ม สิ่งสำคัญคือต้องคำนึงถึงการเข้าถึงได้เพื่อให้แน่ใจว่าผู้ใช้ที่มีความพิการสามารถใช้ฟอร์มของคุณได้อย่างมีประสิทธิภาพ useFormState สามารถช่วยคุณสร้างฟอร์มที่เข้าถึงได้โดยการจัดเตรียมกลไกสำหรับการจัดการข้อผิดพลาดและให้ผลตอบรับแก่ผู้ใช้ นี่คือแนวทางปฏิบัติที่ดีที่สุดด้านการเข้าถึงได้:

แนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ useFormState

เพื่อให้ได้ประโยชน์สูงสุดจาก useFormState hook ให้พิจารณาแนวทางปฏิบัติที่ดีที่สุดต่อไปนี้:

ตัวอย่างและกรณีการใช้งานในโลกแห่งความเป็นจริง

useFormState สามารถใช้ได้ในแอปพลิเคชันจริงที่หลากหลาย นี่คือตัวอย่างบางส่วน:

ตัวอย่างเช่น ลองพิจารณาฟอร์มชำระเงินใน e-commerce การใช้ useFormState ทำให้คุณสามารถจัดการการตรวจสอบความถูกต้องของที่อยู่จัดส่ง ข้อมูลการชำระเงิน และรายละเอียดคำสั่งซื้ออื่นๆ บนเซิร์ฟเวอร์ได้ ซึ่งช่วยให้แน่ใจว่าข้อมูลถูกต้องก่อนที่จะส่งไปยังฐานข้อมูล และยังช่วยปรับปรุงประสิทธิภาพโดยการลดการประมวลผลฝั่งไคลเอ็นต์อีกด้วย

อีกตัวอย่างหนึ่งคือฟอร์มลงทะเบียนผู้ใช้ การใช้ useFormState ทำให้คุณสามารถจัดการการตรวจสอบความถูกต้องของชื่อผู้ใช้ รหัสผ่าน และที่อยู่อีเมลบนเซิร์ฟเวอร์ได้ ซึ่งช่วยให้แน่ใจว่าข้อมูลมีความปลอดภัยและผู้ใช้ได้รับการยืนยันตัวตนอย่างถูกต้อง

สรุป

useFormState hook ของ React เป็นวิธีที่มีประสิทธิภาพในการจัดการสถานะของฟอร์มและปรับปรุงตรรกะการจัดการฟอร์มให้ง่ายขึ้น ด้วยการใช้ประโยชน์จาก Server Actions และ progressive enhancement useFormState ช่วยให้คุณสามารถสร้างฟอร์มที่แข็งแกร่ง มีประสิทธิภาพ และเข้าถึงได้ ซึ่งมอบประสบการณ์ที่ยอดเยี่ยมแก่ผู้ใช้ โดยการปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดที่ระบุไว้ในคู่มือนี้ คุณสามารถใช้ useFormState ได้อย่างมีประสิทธิภาพเพื่อลดความซับซ้อนของตรรกะการจัดการฟอร์มและสร้างแอปพลิเคชัน React ที่ดียิ่งขึ้น อย่าลืมพิจารณามาตรฐานการเข้าถึงได้ระดับโลกและความคาดหวังของผู้ใช้เมื่อออกแบบฟอร์มสำหรับผู้ชมที่หลากหลายจากนานาชาติ