メインコンテンツへ移動

เนื้อหาภาษาไทย / タイ語のコンテンツ

システムガイド 内容確認済み

Context API: ทางเลือกสำหรับ Global State อย่างง่าย

บทความนี้แนะนำ Context API ใน React ซึ่งเป็นเครื่องมือสำหรับจัดการ Global State อย่างง่าย ลดปัญหา Prop Drilling โดยสร้าง "บริบท" ที่ Component ต่างๆ สามารถเข้าถ...

Context API: ทางเลือกสำหรับ Global State อย่างง่าย

จากบทที่แล้ว เราได้เรียนรู้การใช้ useState Hook ใน React เพื่อจัดการ State ภายใน Component แต่ถ้าเราต้องการแชร์ State ข้าม Component หลายๆ ตัวที่อยู่ลึกลงไปในโครงสร้าง Component ล่ะ? การส่ง Props ลงไปเรื่อยๆ (Prop Drilling) อาจไม่ใช่ทางเลือกที่ดีนัก เพราะทำให้โค้ดอ่านยากและดูแลรักษายาก

Context API ใน React จึงเข้ามาช่วยแก้ปัญหานี้ Context API เป็นเครื่องมือที่ช่วยให้เราสามารถสร้าง "บริบท" (Context) ที่เก็บ State และฟังก์ชันต่างๆ ไว้ จากนั้น Component ต่างๆ ที่อยู่ใน Context เดียวกันจะสามารถเข้าถึงและแก้ไข State เหล่านั้นได้โดยตรง โดยไม่ต้องส่ง Props ผ่าน Component หลายๆ ชั้น

Context API เหมาะกับใคร?

Context API เหมาะสำหรับจัดการ Global State ขนาดเล็กถึงกลาง เช่น ข้อมูลผู้ใช้ที่ Login แล้ว, Theme ของเว็บไซต์ (Light/Dark Mode) หรือภาษาที่ใช้ในแอปพลิเคชัน

ข้อควรระวัง: Context API อาจไม่เหมาะกับแอปพลิเคชันขนาดใหญ่ที่มี State ซับซ้อนมากๆ เพราะอาจทำให้ยากต่อการจัดการและ Debug ในกรณีนี้ การใช้ State Management Library อย่าง Redux หรือ Zustand อาจเป็นทางเลือกที่ดีกว่า

การสร้าง Context

ในการสร้าง Context เราจะใช้ React.createContext() API ซึ่งจะคืนค่า Context Object ออกมา Context Object นี้ประกอบไปด้วย Provider และ Consumer

// สร้าง Context
import React from 'react';

const MyContext = React.createContext();

export default MyContext;

คำอธิบาย:

  • React.createContext(): ฟังก์ชันนี้สร้าง Context Object ใหม่
  • MyContext: ชื่อ Context ที่เราตั้งขึ้น สามารถตั้งชื่ออะไรก็ได้ที่สื่อถึงข้อมูลที่เราจะเก็บใน Context
  • export default MyContext: เรา export Context ออกไปเพื่อให้ Component อื่นๆ สามารถนำไปใช้ได้

การใช้ Provider

Provider เป็น Component ที่ใช้ห่อ Component อื่นๆ ที่ต้องการเข้าถึง Context Provider จะรับ Props ชื่อ value ซึ่งเป็นค่า State หรือฟังก์ชันที่เราต้องการแชร์ให้กับ Component ที่อยู่ใน Context

// Component หลัก (App.js)
import React, { useState } from 'react';
import MyContext from './MyContext';
import ChildComponent from './ChildComponent';

function App() {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
  };

  const contextValue = {
    theme: theme,
    toggleTheme: toggleTheme
  };

  return (
    <MyContext.Provider value={contextValue}>
      <div>
        <h1>Theme: {theme}</h1>
        <button onClick={toggleTheme}>Toggle Theme</button>
        <ChildComponent />
      </div>
    </MyContext.Provider>
  );
}

export default App;

คำอธิบาย:

  • <MyContext.Provider value={contextValue}>: เราห่อ Component ทั้งหมดด้วย MyContext.Provider และส่ง contextValue เป็น Props value
  • contextValue: เป็น Object ที่เก็บ State theme และฟังก์ชัน toggleTheme ที่เราต้องการแชร์
  • ChildComponent: เป็น Component ลูกที่อยู่ใน Context นี้

การใช้ Consumer หรือ useContext Hook

Component ที่ต้องการเข้าถึง State ใน Context สามารถทำได้ 2 วิธี:

  1. Consumer: ใช้ MyContext.Consumer Component
  2. useContext Hook: ใช้ useContext(MyContext) Hook (วิธีนี้เป็นที่นิยมมากกว่า)

การใช้ Consumer

// ChildComponent.js
import React from 'react';
import MyContext from './MyContext';

function ChildComponent() {
  return (
    <MyContext.Consumer>
      {context => (
        <div>
          <h2>Child Component</h2>
          <p>Current Theme: {context.theme}</p>
          <button onClick={context.toggleTheme}>Toggle Theme</button>
        </div>
      )}
    </MyContext.Consumer>
  );
}

export default ChildComponent;

คำอธิบาย:

  • <MyContext.Consumer>: เราใช้ MyContext.Consumer เพื่อเข้าถึง Context
  • {context => ...}: Consumer จะรับฟังก์ชันเป็น Child ฟังก์ชันนี้จะรับ Context Value เป็น Argument (ในที่นี้คือ context)
  • เราสามารถเข้าถึง context.theme และ context.toggleTheme ได้โดยตรง

การใช้ useContext Hook (วิธีที่แนะนำ)

// ChildComponent.js
import React, { useContext } from 'react';
import MyContext from './MyContext';

function ChildComponent() {
  const context = useContext(MyContext);

  return (
    <div>
      <h2>Child Component</h2>
      <p>Current Theme: {context.theme}</p>
      <button onClick={context.toggleTheme}>Toggle Theme</button>
    </div>
  );
}

export default ChildComponent;

คำอธิบาย:

  • import { useContext } from 'react';: เรา import useContext Hook จาก React
  • const context = useContext(MyContext);: เราเรียกใช้ useContext Hook โดยส่ง Context Object (MyContext) เป็น Argument Hook จะคืนค่า Context Value ออกมา (ในที่นี้คือ Object ที่มี theme และ toggleTheme)
  • เราสามารถเข้าถึง context.theme และ context.toggleTheme ได้โดยตรง

สรุป: การใช้ useContext Hook ทำให้โค้ดอ่านง่ายและกระชับกว่าการใช้ Consumer

ข้อดีข้อเสียของ Context API

ข้อดี:

  • ใช้งานง่าย: Context API เป็นส่วนหนึ่งของ React ทำให้ไม่ต้องติดตั้ง Library เพิ่มเติม
  • ลด Prop Drilling: ช่วยลดความซับซ้อนในการส่ง Props ผ่าน Component หลายๆ ชั้น
  • เหมาะกับ Global State ขนาดเล็กถึงกลาง: เหมาะสำหรับจัดการข้อมูลที่ไม่ซับซ้อนมากนัก

ข้อเสีย:

  • Re-renders: ทุก Component ที่อยู่ใน Context จะ Re-render เมื่อ Context Value เปลี่ยนแปลง แม้ว่า Component นั้นจะไม่ได้ใช้ State ที่เปลี่ยนแปลงก็ตาม ทำให้เกิดปัญหา Performance ได้
  • Debugging ยาก: อาจยากต่อการ Debug เมื่อ Context มีความซับซ้อน
  • ไม่เหมาะกับ State ที่ซับซ้อนมากๆ: สำหรับ State ที่ซับซ้อนมากๆ การใช้ State Management Library อาจเป็นทางเลือกที่ดีกว่า

กรณีใช้งานจริงและข้อผิดพลาดที่พบบ่อย

กรณีใช้งานจริง:

  • Theme Switching: เปลี่ยน Theme ของเว็บไซต์ (Light/Dark Mode)
  • Language Switching: เปลี่ยนภาษาที่ใช้ในแอปพลิเคชัน
  • Authentication: จัดการข้อมูลผู้ใช้ที่ Login แล้ว

ข้อผิดพลาดที่พบบ่อย:

  • Re-renders มากเกินไป: แก้ไขได้โดยใช้ React.memo หรือ useMemo เพื่อป้องกัน Component Re-render โดยไม่จำเป็น
  • อัพเดท State โดยตรง: ควรใช้ฟังก์ชันอัพเดท State ที่ Context Provider ให้มา เพื่อให้มั่นใจว่า Component ที่ใช้ Context จะได้รับการแจ้งเตือนเมื่อ State เปลี่ยนแปลง
  • Context ซับซ้อนเกินไป: ถ้า Context เริ่มซับซ้อนมากเกินไป ควรพิจารณาใช้ State Management Library แทน

ในบทต่อไป เราจะมาเรียนรู้เกี่ยวกับ State Management Library ที่ได้รับความนิยมอย่าง Redux กันครับ

Office.in.th Custom Service

この構成をもとにシステムを開発・カスタマイズしたいですか?

Office.in.th は、エンタープライズ Web アプリケーション、API 連携、官民の業務管理システムの設計・開発を承り、長期的なサポートも提供します。

ソフトウェア開発サービスを見る