ReactJS คือ ตอนที่ 4 : React Hooks

  1. React Hooks คืออะไร
  2. ทำไมต้องใช้ Hooks
  3. React Hooks ที่ใช้กันทั่วไป
    3.1 useState
    3.2 useEffect
    3.3 useContext
    3.4 useRef
    3.5 useReducer
  4. Hooks แบบกำหนดเอง (Custom)
  5. React Hooks และอนาคตของการสร้างแอพ
    5.1 ส่วนประกอบการทำงาน (Functional Components) เป็นผู้นำ
    5.2 การจัดการสถานะและเอฟเฟกต์แบบง่าย
    5.3 ปรับปรุงการใช้โค้ดซ้ำ (Code Reuse) และการห่อหุ้มลอจิก (Logic Encapsulation)
    5.4 การจัดการพร้อมกัน (Concurrency) ที่ดีขึ้นด้วยโหมด Suspense และ Concurrent

เมื่อทำเว็บ ReactJS และทำแอพ สิ่งสำคัญอย่างหนึ่งที่ต้องทำความเข้าใจคือ React Hooks ในโลกที่ไม่หยุดนิ่งของการพัฒนาเว็บ React ได้กลายเป็นผู้เล่นที่ปฏิวัติวงการ โดยเปลี่ยนวิธีที่เราจัดโครงสร้างส่วนประกอบของ (components) เราและจัดการสถานะและวิธีการวงจรชีวิตภายในส่วนประกอบ (components) เหล่านั้น

ก่อนเปิดตัว Hooks ใน React เวอร์ชัน 16.8 วิธีสถานะและวงจรชีวิตมีให้ใช้งานในส่วนประกอบของคลาสเท่านั้น คอมโพเนนต์ของฟังก์ชันหรือที่เรียกว่าคอมโพเนนต์ ‘stateless’ มีหน้าที่เพียงแสดงผล UI โดยไม่มีความสามารถในการจัดการเมธอดสถานะหรือวงจรชีวิต (handle state or lifecycle methods) แต่ Hooks ได้เปลี่ยนสถานการณ์นี้ โดยเพิ่มฟังก์ชันการทำงานให้กับส่วนประกอบของฟังก์ชันและทำให้มีความหลากหลายมากขึ้น

1. React Hooks คืออะไร

React Hooks เป็นฟังก์ชันในตัวที่ช่วยให้คุณสามารถใช้สถานะและคุณลักษณะ React อื่นๆ ในส่วนประกอบการทำงานได้ ก่อนใช้ Hooks คุณจะต้องแปลงส่วนประกอบการทำงานเป็นส่วนประกอบของคลาสเพื่อใช้ state หรือ lifecycle method ซึ่งเป็นกระบวนการที่น่าเบื่อ ด้วย Hooks ตอนนี้คุณสามารถใช้ประโยชน์จากคุณสมบัติอันทรงพลังเหล่านี้ในองค์ประกอบการทำงานของคุณโดยไม่ต้องเขียนคลาส สิ่งนี้มีส่วนอย่างมากในการทำเว็บ ReactJS และทำแอพที่สะอาดขึ้น เข้าใจได้มากขึ้น และจัดการได้ง่ายขึ้น

2. ทำไมต้องใช้ Hooks

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

3. React Hooks ที่ใช้กันทั่วไป

3.1 useState

hook useState ช่วยให้คุณเพิ่มสถานะให้กับส่วนประกอบการทำงาน ส่งคืนอาร์เรย์ที่มีค่าสถานะปัจจุบันและฟังก์ชันเพื่ออัปเดตสถานะนั้น

นี่คือตัวอย่างuseStateการดำเนินการ:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

ในตัวอย่างนี้ useState เริ่มต้น count ตัวแปรสถานะเป็น 0 setCountเป็นฟังก์ชันที่ใช้ในการอัพเดตสถานะ เมื่อคลิกปุ่ม ฟังก์ชัน setCount จะถูกเรียกใช้ด้วยค่าสถานะใหม่

3.2 useEffect

hook useEffect เป็นตัวแทนที่โดยตรงสำหรับ lifecycle method เช่น componentDidMount, componentDidUpdate, และcomponentWillUnmountในส่วนประกอบของฟังก์ชัน hook useEffect ถูกเรียกหลังจากเรนเดอร์ถูกส่งไปยังหน้าจอ

นี่คือตัวอย่างของ useEffect:

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

ในตัวอย่างข้างต้น useEffecthook จะอัปเดตชื่อเอกสารหลังจาก React อัปเดต DOM สิ่งนี้จำลอง componentDidUpdate วิธีวงจรชีวิตจากส่วนประกอบของคลาส

3.3 useContext

hook useContext เป็นวิธีการส่งผ่านข้อมูลผ่านแผนผังส่วนประกอบโดยไม่ต้องผ่านอุปกรณ์ประกอบฉากด้วยตนเองในทุกระดับ อนุญาตให้คุณแชร์ค่าหรือข้อมูลบางอย่างกับคอมโพเนนต์ทั้งหมดในแผนผัง เช่น ผู้ใช้ปัจจุบัน ธีม หรือการตั้งค่าภาษา

3.4 useRef

hook useRef มีประโยชน์เมื่อคุณต้องการอ้างอิงองค์ประกอบโดยตรง สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อต้องจัดการกับอินพุตฟอร์ม ซึ่งคุณต้องการดึงค่าปัจจุบันขององค์ประกอบ หรือกับแอนิเมชันที่คุณต้องการเข้าถึงคุณสมบัติขององค์ประกอบ DOM

นี่คือตัวอย่างของ useRef:

import React, { useRef } from 'react';

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

ในตัวอย่างนี้ useRef ใช้เพื่ออ้างอิงถึงองค์ประกอบอินพุต วิธี focus การนี้จะถูกนำมาใช้ในการอ้างอิงนี้เพื่อโฟกัสอินพุตโดยทางโปรแกรมเมื่อคลิกปุ่ม

3.5 useReducer

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

นี่คือตัวอย่างของ useReducer:

import React, { useReducer } from 'react';

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
  );
}

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

4. Hooks แบบกำหนดเอง (Custom)

นอกเหนือจาก hooks ในตัวแล้ว React ยังให้คุณสร้าง hooks ของคุณเอง ซึ่งเรียกกันทั่วไปว่า hooks แบบกำหนดเอง hooks ที่กำหนดเองเหล่านี้คือฟังก์ชัน JavaScript ที่ชื่อนำหน้าด้วยคำว่า ‘use’ hook ที่กำหนดเองสามารถมีการรวมกันของคุณสมบัติ React เช่น state และ lifecycle method

hooks แบบกำหนดเองช่วยให้คุณสามารถสรุปและแบ่งปันพฤติกรรมทั่วไปในส่วนประกอบต่างๆ ของคุณ ตัวอย่างเช่น หากคุณมีคอมโพเนนต์หลายรายการที่ต้องโต้ตอบกับ API หนึ่งๆ คุณสามารถสร้าง hook แบบกำหนดเองที่จัดการการเรียก API และส่งคืนสถานะ โดยจะอัปเดตเมื่อข้อมูลเปลี่ยนแปลง

ต่อไปนี้คือตัวอย่าง hook แบบกำหนดเองอย่างง่าย:

import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch(url)
      .then((response) => response.json())
      .then((data) => setData(data));
  }, [url]);

  return data;
}

ในตัวอย่างนี้useFetchเป็น hook แบบกำหนดเองที่ดึงข้อมูลจาก URL และตั้งค่าข้อมูลเป็นสถานะ ตอนนี้คุณสามารถใช้ hook ที่กำหนดเองนี้กับส่วนประกอบใดๆ ของคุณเพื่อดึงข้อมูลและแสดงข้อมูลได้อย่างง่ายดาย

5. React Hooks และอนาคตของการสร้างแอพ

การเปิดตัว hooks ส่งผลกระทบอย่างมากต่อวิธีที่เราดำเนินการเกี่ยวกับการทำเว็บ ReactJS และทำแอพด้วยการช่วยให้เราใช้สถานะและคุณลักษณะ React อื่นๆ โดยไม่ต้องเขียนส่วนประกอบของคลาส hooks ทำให้โค้ดของเราสะอาดขึ้น มีประสิทธิภาพมากขึ้น และอ่านและบำรุงรักษาได้ง่ายขึ้น แต่สิ่งนี้มีความหมายอย่างไรต่ออนาคตของการทำเว็บ ReactJS และทำแอพ

คำตอบอยู่ในธรรมชาติของ Hooks เอง เมื่อส่วนประกอบการทำงานมีประสิทธิภาพมากขึ้นด้วยการใช้ hooks เรากำลังก้าวไปสู่ ​​codebase ที่มีโอกาสเกิดข้อผิดพลาดน้อยลง มีโมดูลมากขึ้น และเข้าใจง่ายขึ้น

5.1 ส่วนประกอบการทำงาน (Functional Components) เป็นผู้นำ

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

5.2 การจัดการสถานะและเอฟเฟกต์แบบง่าย

การจัดการสถานะและผลข้างเคียงอาจค่อนข้างท้าทายในการใช้งานขนาดใหญ่ การแนะนำ hook เช่น useState และ useEffect ทำให้การจัดการสถานะและเอฟเฟกต์ง่ายขึ้นมาก hooks useState ทำให้ง่ายต่อการเพิ่มสถานะให้กับส่วนประกอบที่ใช้งานได้ ในขณะที่ useEffect hooks ช่วยให้คุณแสดงผลข้างเคียงในส่วนประกอบของคุณ hooks เหล่านี้ไม่เพียงแต่ทำให้การจัดการ state และ effect ง่ายขึ้น แต่ยังช่วยให้โค้ดของคุณดีขึ้น (Don’t Repeat Yourself)

5.3 ปรับปรุงการใช้โค้ดซ้ำ (Code Reuse) และการห่อหุ้มลอจิก (Logic Encapsulation)

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

5.4 การจัดการพร้อมกัน (Concurrency) ที่ดีขึ้นด้วยโหมด Suspense และ Concurrent

แม้จะไม่ได้เชื่อมโยงกับ hooks โดยตรง แต่โหมด Suspense และ Concurrent ก็เป็นคุณสมบัติใหม่ที่ได้รับประโยชน์จากสถาปัตยกรรมที่อิงกับ hook โหมดทำงานพร้อมกันช่วยให้การอัปเดตหลายสถานะเกิดขึ้นพร้อมกัน ในขณะที่ Suspense ช่วยให้คอมโพเนนต์ของคุณ “wait” บางอย่างก่อนที่จะแสดงผลได้ เช่น การดึงข้อมูล ฟีเจอร์เหล่านี้ใช้ประโยชน์จากส่วนประกอบของฟังก์ชันได้ง่ายขึ้นโดยใช้ hooks ช่วยให้ผู้ใช้ได้รับประสบการณ์ที่ลื่นไหลมากขึ้น


โดยสรุป hooks เป็นก้าวกระโดดที่สำคัญในการทำเว็บ ReactJS และทำแอพ พวกเขานำมาซึ่งการเปลี่ยนแปลงกระบวนทัศน์ในวิธีที่เราเขียนโค้ด React ให้ความสำคัญกับส่วนประกอบของฟังก์ชัน และส่งเสริมการใช้โค้ดซ้ำและการห่อหุ้มตรรกะ Hooks นำเสนอวิธีจัดการสถานะและผลข้างเคียงที่ง่ายและเป็นธรรมชาติมากขึ้น และปูทางสำหรับคุณสมบัติในอนาคต เช่น โหมด Suspense และ Concurrent

ขณะที่เราสำรวจศักยภาพของ hooks ใน React ต่อไป เราตั้งตารอที่จะทำเว็บ ReactJS และทำแอพที่มีประสิทธิภาพ บำรุงรักษาได้ และแข็งแกร่งยิ่งขึ้น เป็นช่วงเวลาที่น่าตื่นเต้นในการเป็นนักพัฒนา React และเราแทบรอไม่ไหวที่จะได้เห็นว่า hooks กำหนดอนาคตของการทำเว็บ ReactJS และทำแอพได้อย่างไร


React คืออะไร (ReactJS)

ReactJS คือ ตอนที่ 3 : สถานะ (State) และ Props
ReactJS คือ ตอนที่ 5 : การจัดการเหตุการณ์ (Event Handling)