😎 React TypeScript

เจาะลึก useEffect และ TypeScript: วิธีจัดการ Side Effects และ Lifecycle ใน React

9 นาที 21 views บันทึกเป็น PDF
เจาะลึก useEffect และ TypeScript: วิธีจัดการ Side Effects และ Lifecycle ใน React

เรียนรู้วิธีใช้ useEffect ใน React ร่วมกับ TypeScript ให้แม่นยำ ทั้งการจัดการ Dependency Array, การทำ Cleanup Function และการระบุ Type เพื่อลดบั๊กในแอป

ทำความรู้จักกับ useEffect และ Side Effects

เวลาเราเขียนเว็บด้วย React (ไลบรารีสำหรับสร้างหน้าจอผู้ใช้) บางครั้งเราต้องทำอะไรที่อยู่นอกเหนือการแสดงผลปกติ เช่น การดึงข้อมูลจากเซิร์ฟเวอร์ หรือการตั้งเวลาแจ้งเตือน งานพวกนี้เราเรียกว่า Side Effects (งานที่ส่งผลกระทบต่อภายนอกระบบ) เปรียบเหมือนเวลาเราทำอาหาร ถ้าแค่หั่นผักใส่จานนั่นคือการแสดงผล แต่ถ้าเราต้องเปิดเตาแก๊สหรือล้างจานเพิ่ม นั่นคือ Side Effects ที่เกิดขึ้นระหว่างทาง

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

เมื่อเราใช้ร่วมกับ TypeScript (ภาษาที่ช่วยระบุประเภทข้อมูลให้โค้ด) เราจะสามารถควบคุมข้อมูลที่ส่งเข้าและออกจาก useEffect ได้แม่นยำขึ้น การระบุ Type (ชนิดข้อมูล) จะช่วยลดบั๊ก (ข้อผิดพลาดของโปรแกรม) ที่เกิดจากการพิมพ์ผิดหรือใช้ข้อมูลผิดประเภท ทำให้เราทำงานได้เร็วขึ้นและมั่นใจกว่าเดิม

import { useEffect } from 'react';

// ตัวอย่างการใช้งาน useEffect เบื้องต้น
const MyComponent = () => {
  useEffect(() => {
    console.log("ทำงานทุกครั้งที่คอมโพเนนต์แสดงผล");
  });

  return <div>สวัสดีครับ</div>;
};

การจัดการ Dependency Array ให้ถูกจุด

Dependency Array (อาร์เรย์รายการตัวแปรที่ต้องเฝ้าสังเกต) คือช่องว่างด้านหลัง useEffect ที่เอาไว้ใส่ตัวแปรที่เราต้องการให้มันคอยตรวจสอบ ถ้าตัวแปรในนี้เปลี่ยนไป useEffect ถึงจะทำงานอีกครั้ง เปรียบเหมือนเซนเซอร์ไฟอัตโนมัติที่จะเปิดไฟก็ต่อเมื่อมีคนเดินผ่าน ถ้าไม่มีใครเดินผ่าน ไฟก็ไม่ต้องเปิดให้เปลืองพลังงาน

ถ้าเราปล่อยช่องนี้ว่างไว้ (ไม่ใส่อะไรเลย) useEffect จะทำงานทุกครั้งที่มีการอัปเดตหน้าจอ ซึ่งมักจะไม่ใช่สิ่งที่เราต้องการ ถ้าเราใส่ [] (อาร์เรย์ว่าง) มันจะทำงานแค่ตอนที่หน้าจอโหลดขึ้นมาครั้งแรกเท่านั้น การเลือกใส่ให้ถูกคือหัวใจสำคัญของการเขียนโปรแกรมที่มีประสิทธิภาพ

มือใหม่มักพลาดโดยการลืมใส่ตัวแปรที่ใช้งานจริงลงไปใน Dependency Array ทำให้ค่าที่แสดงผลบนหน้าจอไม่ยอมอัปเดตตามความเป็นจริง วิธีเช็กง่ายๆ คือ ให้ใส่ตัวแปรทุกตัวที่เราเรียกใช้ใน useEffect ลงไปในอาร์เรย์นี้ แล้วโปรแกรมจะทำงานได้ถูกต้องตามที่เราคาดหวังไว้เสมอ

import { useEffect, useState } from 'react';

const UserProfile = ({ userId }: { userId: number }) => {
  useEffect(() => {
    console.log("ดึงข้อมูลผู้ใช้ใหม่เมื่อ userId เปลี่ยน:", userId);
  }, [userId]); // ใส่ userId ลงไป เพื่อให้มันทำงานใหม่เฉพาะตอน id เปลี่ยน

  return <div>แสดงข้อมูลผู้ใช้ {userId}</div>;
};

การทำ Cleanup Function เพื่อคืนค่าทรัพยากร

Cleanup Function (ฟังก์ชันสำหรับล้างข้อมูลเก่า) คือฟังก์ชันที่เราเขียนไว้ข้างใน useEffect เพื่อยกเลิกงานที่ค้างอยู่ก่อนที่ useEffect จะเริ่มทำงานรอบใหม่ หรือตอนที่คอมโพเนนต์ถูกลบออกไปแล้ว เปรียบเหมือนการปิดไฟและล็อกห้องก่อนออกจากบ้าน ถ้าเราไม่ทำความสะอาดให้เรียบร้อย อาจจะเกิดปัญหาข้อมูลค้างในระบบได้

เราสร้างมันได้ง่ายๆ โดยการใช้คำสั่ง return แล้วตามด้วยฟังก์ชันข้างใน useEffect อีกทีหนึ่ง มันมีประโยชน์มากเวลาเราทำระบบแจ้งเตือนที่ต้องตั้งเวลาไว้ หรือการดึงข้อมูลที่อาจจะยังไม่เสร็จแล้วผู้ใช้กดเปลี่ยนหน้าไปก่อน ถ้าเราไม่ Cleanup (ล้างข้อมูลเก่า) อาจเกิดการอัปเดตค่าในคอมโพเนนต์ที่ไม่มีอยู่จริงจนโปรแกรมพังได้

หลายคนมักละเลยขั้นตอนนี้เพราะคิดว่าแค่เขียนโค้ดให้ทำงานได้ก็พอ แต่ในโลกของการทำงานจริง การจัดการหน่วยความจำ (พื้นที่เก็บข้อมูลชั่วคราวของโปรแกรม) เป็นเรื่องสำคัญมาก การหัดเขียน Cleanup Function จะช่วยให้แอปพลิเคชันของคุณดูเป็นมืออาชีพและไม่กินทรัพยากรเครื่องของผู้ใช้เกินความจำเป็น

useEffect(() => {
  const timer = setInterval(() => {
    console.log("ทำงานทุกๆ 1 วินาที");
  }, 1000);

  // ทำการล้างเวลาเมื่อคอมโพเนนต์ถูกเอาออกไป
  return () => clearInterval(timer);
}, []);

ระบุ Type ตัวแปรภายใน Effect

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

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

การฝึกเขียน Type ให้ติดเป็นนิสัยจะทำให้คุณก้าวข้ามจากการเป็นมือใหม่สู่ระดับโปรแกรมเมอร์มืออาชีพได้เร็วขึ้น เพราะมันจะช่วยลดเวลาในการไล่หาบั๊ก (การหาจุดผิดพลาดของโค้ด) ได้มหาศาล ยิ่งงานในทีมมีขนาดใหญ่เท่าไหร่ ความชัดเจนของ Type ยิ่งช่วยให้คนอื่นในทีมเข้าใจโค้ดของคุณได้ง่ายขึ้นเท่านั้น

interface User {
  id: number;
  name: string;
}

useEffect(() => {
  const fetchUser = async () => {
    const response = await fetch('/api/user');
    const data: User = await response.json(); // ระบุ Type ให้ข้อมูลที่ได้มา
    console.log(data.name);
  };
  fetchUser();
}, []);

จุดที่มือใหม่มักพลาดและวิธีแก้ไข

ปัญหาที่เจอบ่อยที่สุดคือการใส่ตัวแปรผิดประเภทลงใน Dependency Array จนทำให้เกิดการทำงานไม่รู้จบ หรือที่เรียกว่า Infinite Loop (การทำงานวนซ้ำไม่สิ้นสุด) เปรียบเหมือนการที่เราตั้งเงื่อนไขว่า "ถ้าไฟเปิด ให้เปิดไฟ" มันจะวนลูปจนค่าไฟพุ่งและระบบรวน วิธีแก้คือต้องตรวจดูเสมอว่าตัวแปรในอาร์เรย์นั้นเป็นค่าคงที่หรือค่าที่เปลี่ยนแปลงได้จริงๆ

อีกจุดคือการลืมจัดการกับ Async/Await (คำสั่งจัดการงานที่ใช้เวลานาน) ภายใน useEffect โดยตรง เพราะ useEffect ไม่รองรับฟังก์ชันแบบ Async โดยตรง วิธีที่ถูกต้องคือการสร้างฟังก์ชันแยกไว้ข้างในแล้วค่อยเรียกใช้ หรือใช้การจัดการสถานะให้ดีขึ้นเพื่อป้องกันข้อมูลไหลเข้ามาระหว่างที่คอมโพเนนต์กำลังทำงาน

สุดท้ายคือการไม่เช็กสถานะก่อนอัปเดตข้อมูล ถ้าคอมโพเนนต์ถูกทำลายไปแล้ว (ถูกเอาออกจากหน้าจอ) แต่เรายังพยายามอัปเดตค่าอยู่ จะเกิดข้อผิดพลาดขึ้นเสมอ ให้ใช้ตัวแปรแบบ boolean (ค่าจริงหรือเท็จ) เข้ามาช่วยเช็กสถานะว่าคอมโพเนนต์ยังทำงานอยู่หรือไม่ก่อนจะสั่งอัปเดตค่าใดๆ ลงไปในหน้าจอ

  1. สร้างฟังก์ชันภายใน useEffect เพื่อจัดการงานที่ต้องรอเวลา
  2. ระบุ Type ให้ข้อมูลที่ได้รับมาเพื่อป้องกันการเข้าถึงค่าผิดพลาด
  3. ใส่ Dependency Array ให้ครบถ้วนตามตัวแปรที่เรียกใช้
  4. เขียน Cleanup Function เพื่อคืนค่าทรัพยากรทุกครั้งที่มีการใช้ตัวจับเวลา

สรุปและแนวทางการฝึกฝน

การใช้ useEffect และ TypeScript อาจดูยากในตอนแรก แต่มันเป็นรากฐานสำคัญของการพัฒนาเว็บสมัยใหม่ เริ่มต้นให้ลองสร้างโปรเจกต์เล็กๆ เช่น แอปนาฬิกาจับเวลา หรือแอปดึงข้อมูลรายชื่อเพื่อนมาฝึกฝน การลงมือทำจริงจะทำให้คุณเห็นภาพว่า Dependency Array และ Cleanup Function มีผลอย่างไรในสถานการณ์จริง

จำไว้ว่าโปรแกรมเมอร์ที่เก่งไม่ได้เก่งเพราะจำคำสั่งได้ทั้งหมด แต่เก่งเพราะรู้วิธีจัดการกับปัญหาและเครื่องมือที่ใช้ ถ้าคุณเจอบั๊ก อย่าเพิ่งท้อ ให้ใช้เครื่องมืออย่าง console.log เพื่อดูค่าที่ส่งเข้ามาใน useEffect ทีละขั้นตอน การทำความเข้าใจแต่ละบรรทัดที่คุณเขียนคือเส้นทางสู่การเป็นมืออาชีพที่แท้จริง

หัวใจสำคัญคือความสม่ำเสมอ ลองฝึกเขียนโค้ดวันละ 1 ชั่วโมง โดยเน้นไปที่การลองผิดลองถูกกับ useEffect ให้บ่อยที่สุด เมื่อคุณเริ่มคุ้นเคย คุณจะพบว่าการเขียนโค้ดที่สะอาดและปลอดภัยด้วย TypeScript ไม่ใช่เรื่องน่ากลัวอีกต่อไป ขอให้สนุกกับการเขียนโค้ดครับ!

แชร์บทความ

Facebook X LINE

บทความที่เกี่ยวข้อง

วิธีเช็ก Type ด้วย tsc --noEmit และตั้งค่า Environment Variables ใน React TypeScript ก่อน Deploy
React TypeScript

วิธีเช็ก Type ด้วย tsc --noEmit และตั้งค่า Environment Variables ใน React TypeScript ก่อน Deploy

ไม่อยากให้แอปพังตอน Deploy ต้องอ่าน! สอนวิธีใช้ tsc --noEmit ตรวจสอบข้อผิดพลาดในโปรเจกต์ React TypeScript พร้อมวิธีตั้งค่า Environment Variables ให้ปลอดภัย

1 month ago 8 นาที
22 views
React TypeScript Workshop: จัดการ State, Form และ API ให้ปลอดภัยแบบมือโปร
React TypeScript

React TypeScript Workshop: จัดการ State, Form และ API ให้ปลอดภัยแบบมือโปร

เรียนรู้วิธีเขียน React ด้วย TypeScript ให้โค้ดสะอาดและลดบั๊ก ตั้งแต่การจัดการ Form ด้วย React Hook Form ไปจนถึงการดึงข้อมูล API และทำ Global State แบบ Type Safe

1 month ago 8 นาที
24 views
React TypeScript Workshop: เริ่มต้นเขียนโค้ดแบบมือโปรด้วย Type-First Architecture
React TypeScript

React TypeScript Workshop: เริ่มต้นเขียนโค้ดแบบมือโปรด้วย Type-First Architecture

อยากเขียน React ให้เก่งและบั๊กน้อยลงไหม? มาเรียนรู้วิธีวางโครงสร้างข้อมูล (Type-First) และสร้าง UI Component ที่นำกลับมาใช้ใหม่ได้จริง

1 month ago 7 นาที
23 views