0Pricing
TypeScript Academy · บทเรียน

สถานะและตัวลด; การกำหนดชนิดข้อมูล Context

จัดการสถานะของคอมโพเนนต์ด้วย useState และ useReducer จากนั้นยกระดับสถานะไปไว้ใน Context ที่มีชนิดข้อมูล พร้อมฮุกแบบกำหนดเองที่ปลอดภัย

สถานะและตัวลด; การกำหนดชนิดข้อมูล Context เป็นบทเรียน TypeScript Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน TypeScript Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 3 บทเรียน

บทนำ

เป้าหมาย: เริ่มจากสถานะภายในเครื่องด้วย useState เปลี่ยนไปใช้ตัวลดที่มีชนิดด้วย useReducer แล้วเลื่อนสถานะขึ้นไปไว้ในบริบทที่มีชนิดพร้อมฮุกแบบกำหนดเองที่ปลอดภัย

  • กำหนดแบบจำลองสถานะและการกระทำอย่างชัดเจน
  • ควรเลือกใช้ยูเนียนแบบแยกแยะได้
  • ป้องกันการเข้าถึงบริบท

useState ที่ระบุชนิด

กำกับสถานะด้วยชนิดที่ชัดเจน เช่น number ใช้รูปแบบตัวอัปเดตเพื่อหลีกเลี่ยงคลอเชอร์เก่าในการอัปเดตอย่างรวดเร็ว

import React, { useState } from "react"

export default function Counter() {
  const [count, setCount] = useState<number>(0)

  const inc = () => setCount(c => c + 1)
  const dec = () => setCount(c => c - 1)

  return (
    <div style={{ display: "grid", gap: 8 }}>
      <div>Count: {count}</div>
      <div style={{ display: "flex", gap: 8 }}>
        <button onClick={inc}>+1</button>
        <button onClick={dec}>-1</button>
      </div>
    </div>
  )
}

useReducer ที่ระบุชนิด

กำหนดแบบจำลองการกระทำเป็นยูเนียนแบบแยกแยะได้ ส่วน switch ยังคงครอบคลุมทุกกรณี และข้อมูลที่ส่งมาจะมีชนิดตามแต่ละแขนง

import React, { useReducer } from "react"

type State = { count: number }

type Action =
  | { type: "inc" }
  | { type: "add"; by: number }
  | { type: "reset" }

function reducer(s: State, a: Action): State {
  switch (a.type) {
    case "inc": return { count: s.count + 1 }
    case "add": return { count: s.count + a.by }
    case "reset": return { count: 0 }
  }
}

export default function App() {
  const [state, dispatch] = useReducer(reducer, { count: 0 })
  return (
    <div style={{ display: "grid", gap: 8 }}>
      <div>Count: {state.count}</div>
      <button onClick={() => dispatch({ type: "inc" })}>+1</button>
      <button onClick={() => dispatch({ type: "add", by: 5 })}>+5</button>
      <button onClick={() => dispatch({ type: "reset" })}>Reset</button>
    </div>
  )
}

บริบทและฮุก

สร้าง Context<T | null> จากนั้นเปิดเผยฮุกที่ตรวจสอบค่า null แล้วโยนข้อผิดพลาดหากพบ ผู้ใช้จึงเขียนโค้ดได้เรียบง่ายและมีชนิดที่ถูกต้อง

import React, { createContext, useContext, useReducer } from "react"

type State = { count: number }

type Action = { type: "inc" } | { type: "add"; by: number } | { type: "reset" }

function reducer(s: State, a: Action): State {
  switch (a.type) {
    case "inc": return { count: s.count + 1 }
    case "add": return { count: s.count + a.by }
    case "reset": return { count: 0 }
  }
}

type Ctx = { state: State; dispatch: React.Dispatch<Action> }

const CounterCtx = createContext<Ctx | null>(null)

export function useCounter() {
  const ctx = useContext(CounterCtx)
  if (!ctx) throw new Error("useCounter must be used within CounterProvider")
  return ctx
}

export function CounterProvider({ children }: { children: React.ReactNode }) {
  const [state, dispatch] = useReducer(reducer, { count: 0 })
  return <CounterCtx.Provider value={{ state, dispatch }}>{children}</CounterCtx.Provider>
}

export default function App() {
  return (
    <CounterProvider>
      <Inner />
    </CounterProvider>
  )
}

function Inner() {
  const { state, dispatch } = useCounter()
  return (
    <div style={{ display: "grid", gap: 8 }}>
      <div>Count: {state.count}</div>
      <button onClick={() => dispatch({ type: "inc" })}>+1</button>
    </div>
  )
}

รูปแบบบริบทและตัวลด

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

import React from "react"
import { CounterProvider, useCounter } from "./ctx"

function Controls() {
  const { dispatch } = useCounter()
  return (
    <div style={{ display: "flex", gap: 8 }}>
      <button onClick={() => dispatch({ type: "inc" })}>+1</button>
      <button onClick={() => dispatch({ type: "add", by: 10 })}>+10</button>
      <button onClick={() => dispatch({ type: "reset" })}>Reset</button>
    </div>
  )
}

function View() {
  const { state } = useCounter()
  return <div>Count: {state.count}</div>
}

export default function App() {
  return (
    <CounterProvider>
      <div style={{ display: "grid", gap: 8 }}>
        <View />
        <Controls />
      </div>
    </CounterProvider>
  )
}

แนวทางปฏิบัติที่ดี

แนวทางปฏิบัติที่ดี:

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

ตรวจสอบการระบุชนิดของบริบท

ตรวจสอบอย่างรวดเร็ว: วิธีที่ปลอดภัยในการระบุชนิดของ React Context คืออะไร

สรุปทบทวน

สรุปทบทวน: เริ่มด้วย useState จำลองการเปลี่ยนสถานะด้วย useReducer และเลื่อนสถานะที่ใช้ร่วมกันไปไว้ในบริบทที่มีชนิดซึ่งมีฮุกแบบกำหนดเองคอยป้องกัน

คำถามที่พบบ่อย

บทเรียน “สถานะและตัวลด; การกำหนดชนิดข้อมูล Context” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “สถานะและตัวลด; การกำหนดชนิดข้อมูล Context” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส TypeScript Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 3 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “สถานะและตัวลด; การกำหนดชนิดข้อมูล Context”

จัดการสถานะของคอมโพเนนต์ด้วย useState และ useReducer จากนั้นยกระดับสถานะไปไว้ใน Context ที่มีชนิดข้อมูล พร้อมฮุกแบบกำหนดเองที่ปลอดภัย คุณปฏิบัติ TypeScript Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน TypeScript Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน TypeScript Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน

บทเรียน “สถานะและตัวลด; การกำหนดชนิดข้อมูล Context” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน TypeScript Academy นี้ได้ไหม

ได้ บทเรียน TypeScript Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พร็อพและลูก อีเวนต์แฮนด์เลอร์ และรีฟ
  2. สถานะและตัวลด; การกำหนดชนิดข้อมูล Context
  3. เจเนอริกของคอมโพเนนต์ — เบื้องต้น
← กลับไปที่ TypeScript Academy