Context API — Theme Toggle
Context API คืออะไร?
Section titled “Context API คืออะไร?”Context API เป็นวิธีที่ React มีให้สำหรับ ส่ง data ข้าม component tree โดยไม่ต้องส่ง props ผ่านทุกตัว
flowchart TB
subgraph "Without Context"
A[App] --> B[Layout] --> C[Header] --> D[ThemeButton]
end
subgraph "With Context"
E[App] -->|"ThemeContext"| F[Any Component]
end
ถ้าเปรียบกับการส่งข้อความทางไปรษณีย์ — Context คือกล่องแชร์ที่ทุกคนเข้าถึงได้
สร้าง Theme Context
Section titled “สร้าง Theme Context”Step 1: สร้าง Theme Context
Section titled “Step 1: สร้าง Theme Context”import { createContext, useContext, useState, useEffect, ReactNode } from "react"
type Theme = "light" | "dark"
interface ThemeContextType { theme: Theme toggleTheme: () => void}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
export function ThemeProvider({ children }: { children: ReactNode }) { const [theme, setTheme] = useState<Theme>(() => { // อ่านค่าจาก localStorage หรือ system preference if (typeof window !== "undefined") { const saved = localStorage.getItem("theme") as Theme if (saved) return saved return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" } return "light" })
useEffect(() => { // อัปเดต class ของ HTML element const root = document.documentElement if (theme === "dark") { root.classList.add("dark") } else { root.classList.remove("dark") } localStorage.setItem("theme", theme) }, [theme])
const toggleTheme = () => { setTheme(prev => prev === "light" ? "dark" : "light") }
return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> )}
export function useTheme() { const context = useContext(ThemeContext) if (!context) { throw new Error("useTheme must be used within a ThemeProvider") } return context}Step 2: ใช้งาน ThemeProvider
Section titled “Step 2: ใช้งาน ThemeProvider”import { ThemeProvider } from "./contexts/ThemeContext"
ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <ThemeProvider> <App /> </ThemeProvider> </React.StrictMode>)Step 3: สร้าง Theme Toggle Button
Section titled “Step 3: สร้าง Theme Toggle Button”import { useTheme } from "../contexts/ThemeContext"
export function ThemeToggle() { const { theme, toggleTheme } = useTheme()
return ( <button onClick={toggleTheme} className="p-2 rounded-lg bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors" aria-label={`Switch to ${theme === "light" ? "dark" : "light"} mode`} > {theme === "light" ? "🌙" : "☀️"} </button> )}ใช้งานใน Component ใดก็ได้
Section titled “ใช้งานใน Component ใดก็ได้”import { ThemeToggle } from "./ThemeToggle"
export function Header() { return ( <header className="flex justify-between items-center p-4 bg-white dark:bg-gray-800"> <h1 className="text-xl font-bold dark:text-white">My Portfolio</h1> <ThemeToggle /> </header> )} ตอนนี้ theme จะถูกเก็บใน localStorage ด้วย คนเข้าชมจะเห็น theme ที่เลือกไว้ล่าสุดเสมอ
📝 สรุป
Section titled “📝 สรุป”| สิ่งที่ทำ | คำอธิบาย |
|---|---|
createContext() | สร้าง context object |
useContext() | อ่านค่าจาก context |
Provider | ส่งค่าให้ component ลูก |
useEffect + localStorage | จำ theme ไว้ตลอด |
flowchart LR
ThemeProvider[ThemeProvider<br/>จัดเก็บ state] -->|"theme, toggleTheme"| useTheme[useTheme<br/>Hook]
useTheme --> ThemeToggle[ThemeToggle<br/>UI Button]
classDef important fill:#a78bfa,stroke:#7c3aed,stroke-width:2px
class ThemeProvider,useTheme,ThemeToggle important
🎯 ต่อไป
Section titled “🎯 ต่อไป”02. Zustand — เรียนรู้การใช้ Zustand สำหรับ cart store ที่มีประสิทธิภาพมากขึ้น
Quiz: Context API & Theme
ข้อ 1 / 40%