0Pricing
TypeScript Academy · Lekcja

Własne hooki z generykami i inferencją

Pisanie wielokrotnego użytku własnych hooków z dla wartości, wyników i błędów oraz wykorzystywanie inferencji i ograniczeń w bezpiecznych API

Własne hooki z generykami i inferencją to bezpłatna lekcja TypeScript Academy na CoddyKit. To lekcja 1 z 2. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej TypeScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs TypeScript Academy zawiera 2 lekcji w sumie.

Wprowadzenie

Cel: Zbudować generyczne hooki, które działają naturalnie: typowany hook localStorage, asynchroniczny loader oraz pomocnik do wzorców controlled/uncontrolled. Wykorzystasz inferencję, dzięki czemu kod wywołujący rzadko będzie wymagał adnotacji typów.

  • Zwracanie krotek dla ergonomii znanej z Reacta
  • Używanie ograniczeń, gdy są potrzebne
  • Unikanie any

useLocalStorage<T>

Zwracaj krotkę [value, set], podobnie jak useState. Zachowuj spójność T między wartością a setterem.

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>

Zwracaj obiekt zawierający value, error i loading. Typ value jest wywnioskowywany z obietnicy zwracanej przez 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>

Obsługuj wzorce controlled i uncontrolled za pomocą jednego pomocnika. Krotka zapewnia zgodność 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 })

Inferencja i ograniczenia

Preferuj inferencję z argumentów; dodawaj ograniczenia extends tylko wtedy, gdy hook wymaga konkretnych pól.

// 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")

Wskazówki

Wskazówki:

  • Zwracaj krotki, aby zachować ergonomię Reacta i spójne typowanie.
  • Nigdy nie używaj any w publicznych sygnaturach hooków.
  • Akceptuj aktualizatory (prev) => next, aby wygodnie wykonywać przejścia stanu.

Sprawdzanie typowania hooków

Szybkie sprawdzenie: która sygnatura najlepiej pasuje do generycznego hooka localStorage?

Podsumowanie

Podsumowanie: Zbudowałeś generyczne hooki wykorzystujące inferencję, stosujące ograniczenia tylko wtedy, gdy są konieczne, oraz udostępniające wyniki w postaci krotek lub obiektów, działające jak natywne API Reacta.

Często zadawane pytania

Czy lekcja „Własne hooki z generykami i inferencją” jest bezpłatna?

Tak — pełny tekst „Własne hooki z generykami i inferencją” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu TypeScript Academy, przejdź na CoddyKit PRO. Kurs TypeScript Academy zawiera 2 lekcji w sumie.

Co nauczysz się w „Własne hooki z generykami i inferencją”?

Pisanie wielokrotnego użytku własnych hooków z dla wartości, wyników i błędów oraz wykorzystywanie inferencji i ograniczeń w bezpiecznych API Ćwiczysz TypeScript Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć TypeScript Academy?

Nie wymagamy żadnego doświadczenia. TypeScript Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 2.

Ile czasu zajmuje lekcja „Własne hooki z generykami i inferencją”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji TypeScript Academy?

Tak. Każda lekcja TypeScript Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Własne hooki z generykami i inferencją
  2. Typy Suspense i granic błędów
← Powrót do TypeScript Academy