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

ฮุกแบบกำหนดเองด้วยเจเนอริกและการอนุมาน

เขียนฮุกแบบกำหนดเองที่นำกลับมาใช้ใหม่ได้ด้วย สำหรับค่า ผลลัพธ์ และข้อผิดพลาด พร้อมใช้การอนุมานและข้อจำกัดเพื่อสร้าง API ที่ปลอดภัย

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

บทนำ

เป้าหมาย: สร้างฮุกทั่วไปที่ใช้งานได้เป็นธรรมชาติ ได้แก่ ฮุก localStorage ตัวโหลดแบบอะซิงโครนัส และตัวช่วยสำหรับรูปแบบควบคุม/ไม่ควบคุม คุณจะอาศัยการอนุมานเพื่อให้ผู้เรียกใช้แทบไม่ต้องระบุชนิดเอง

  • คืนค่าทูเพิลเพื่อให้ใช้งานแบบ React ได้สะดวก
  • ใช้ข้อจำกัดเมื่อจำเป็น
  • ไม่ใช้ชนิดใดก็ได้

useLocalStorage<T>

คืนค่าทูเพิล[ค่า, set] เช่นเดียวกับ useState ทำให้ T สอดคล้องกันทั้งในค่าและตัวตั้งค่า

import { useEffect, useState } from "react"

export function useLocalStorage<T>(key: string, initial: T): [T, (v: T | ((prev: T) => T)) => void] {
  const [value, setValue] = useState<T>(() => {
    try {
      const raw = localStorage.getItem(key)
      return raw ? (JSON.parse(raw) as T) : initial
    } catch {
      return initial
    }
  })

  useEffect(() => {
    try { localStorage.setItem(key, JSON.stringify(value)) } catch {}
  }, [key, value])

  const set = (v: T | ((prev: T) => T)) => {
    setValue(prev => (typeof v === "function" ? (v as (p: T) => T)(prev) : v))
  }

  return [value, set]
}

// Usage
// const [user, setUser] = useLocalStorage("user", { id: 1, name: "Ada" })

useAsync<T>

คืนค่าออบเจ็กต์ที่ประกอบด้วยค่า ข้อผิดพลาด และกำลังโหลด ชนิดของ value จะอนุมานจากพรอมิสที่ fn คืนค่า

import { useEffect, useState } from "react"

export function useAsync<T>(fn: () => Promise<T>, deps: unknown[] = []) {
  const [value, setValue] = useState<T | null>(null)
  const [error, setError] = useState<unknown>(null)
  const [loading, setLoading] = useState<boolean>(false)

  useEffect(() => {
    let cancelled = false
    setLoading(true)
    fn().then(
      (v) => { if (!cancelled) { setValue(v); setError(null) } },
      (e) => { if (!cancelled) { setError(e); setValue(null) } }
    ).finally(() => { if (!cancelled) setLoading(false) })
    return () => { cancelled = true }
  }, deps)

  return { value, error, loading }
}

// Usage
// const { value, error, loading } = useAsync(() => fetch("/api").then(r => r.json()))

useControlled<T>

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

import { useState } from "react"

type ControlledProps<T> = {
  value?: T
  defaultValue: T
  onChange?: (v: T) => void
}

export function useControlled<T>({ value, defaultValue, onChange }: ControlledProps<T>): [T, (v: T) => void] {
  const [inner, setInner] = useState<T>(defaultValue)
  const isControlled = value !== undefined
  const current = isControlled ? (value as T) : inner
  const set = (v: T) => { isControlled ? onChange?.(v) : setInner(v) }
  return [current, set]
}

// Usage
// const [v, setV] = useControlled({ value, defaultValue: "", onChange: setValue })

การอนุมานและข้อจำกัด

ควรเลือกใช้การอนุมานจากอาร์กิวเมนต์ เพิ่มข้อจำกัด extends เฉพาะเมื่อฮุกของคุณต้องใช้ฟิลด์บางอย่างโดยเฉพาะ

// Inference works from the initial value
const [settings, setSettings] = useLocalStorage("settings", { theme: "dark", pageSize: 20 })
// T = { theme: string; pageSize: number }

// Constrain T when needed
interface WithId { id: string }
function useById<T extends WithId>(items: T[], id: string) {
  return items.find(x => x.id === id) || null
}

// Usage
const user = useById([{ id: "u1", name: "Ada" }], "u1")

แนวทาง

แนวทาง:

  • คืนค่าทูเพิลเพื่อให้ใช้งานและระบุชนิดได้สม่ำเสมอแบบ React
  • อย่าใช้ any ในลายเซ็นสาธารณะของฮุก
  • รองรับตัวอัปเดต (prev) => next เพื่อให้การเปลี่ยนสถานะใช้งานได้สะดวก

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

ตรวจสอบอย่างรวดเร็ว: ลายเซ็นใดเหมาะกับฮุก localStorage ทั่วไปมากที่สุด

สรุปทบทวน

สรุปทบทวน: คุณสร้างฮุกทั่วไปที่อาศัยการอนุมาน ใช้ข้อจำกัดเฉพาะเมื่อจำเป็น และเปิดเผยผลลัพธ์แบบทูเพิล/ออบเจ็กต์ที่ให้ความรู้สึกเหมือน API ดั้งเดิมของ React

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

บทเรียน “ฮุกแบบกำหนดเองด้วยเจเนอริกและการอนุมาน” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “ฮุกแบบกำหนดเองด้วยเจเนอริกและการอนุมาน”

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

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

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

บทเรียน “ฮุกแบบกำหนดเองด้วยเจเนอริกและการอนุมาน” ใช้เวลานานแค่ไหน

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

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

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

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

  1. ฮุกแบบกำหนดเองด้วยเจเนอริกและการอนุมาน
  2. ชนิดข้อมูล Suspense และขอบเขตข้อผิดพลาด
← กลับไปที่ TypeScript Academy