Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

Typowanie useState i useRef

Hooki React to silniki Twojego kosmicznego statku. TypeScript pozwala określić, jakie dane przepływają przez te silniki, zapewniając bezpieczna nawigacje.

Typowanie useState

Hook useState automatycznie dedukuje typ na podstawie wartości poczatkowej, ale czasem potrzebujesz jawnego typowania:

1import { useState } from 'react';
2
3// Automatyczna dedukcja typu
4const [count, setCount] = useState(0);         // number
5const [name, setName] = useState("Apollo");    // string
6const [active, setActive] = useState(true);    // boolean
7
8// Jawne typowanie - potrzebne gdy początkowa wartość to null lub undefined
9interface Planet {
10  id: number;
11  name: string;
12  type: string;
13}
14
15// Stan może byc Planet lub null
16const [selectedPlanet, setSelectedPlanet] = useState<Planet | null>(null);
17
18// Tablica obiektów - pusta tablica nie mowi TypeScript o typie elementów
19const [planets, setPlanets] = useState<Planet[]>([]);
20
21// Union types
22type Status = "idle" | "loading" | "success" | "error";
23const [status, setStatus] = useState<Status>("idle");

Kiedy jawne typowanie jest konieczne?

1// 1. Poczatkowa wartość null/undefined
2const [user, setUser] = useState<User | null>(null);
3
4// 2. Pusta tablica
5const [items, setItems] = useState<string[]>([]);
6
7// 3. Union types z ograniczonymi wartosciami
8const [theme, setTheme] = useState<"dark" | "light">("dark");
9
10// 4. Zlozony obiekt z opcjonalnymi polami
11interface FormData {
12  name: string;
13  email: string;
14  message?: string;
15}
16const [form, setForm] = useState<FormData>({ name: "", email: "" });

Typowanie useRef

Hook useRef sluzy do przechowywania referencji do elementów DOM lub wartości, które nie powoduja ponownego renderowania:

1import { useRef } from 'react';
2
3// Referencja do elementu DOM
4const inputRef = useRef<HTMLInputElement>(null);
5const divRef = useRef<HTMLDivElement>(null);
6const canvasRef = useRef<HTMLCanvasElement>(null);
7
8function SearchBar() {
9  const inputRef = useRef<HTMLInputElement>(null);
10
11  const focusInput = () => {
12    // inputRef.current może byc null, wiec używamy ?.
13    inputRef.current?.focus();
14  };
15
16  return (
17    <div>
18      <input ref={inputRef} placeholder="Szukaj planety..." />
19      <button onClick={focusInput}>Fokus</button>
20    </div>
21  );
22}

useRef jako "kontener" na wartość

useRef może również przechowywać dowolna wartość, która nie powoduje ponownego renderowania:

1// Timer ID
2const timerRef = useRef<number | null>(null);
3
4function Countdown() {
5  const timerRef = useRef<number | null>(null);
6  const [seconds, setSeconds] = useState(10);
7
8  const start = () => {
9    timerRef.current = window.setInterval(() => {
10      setSeconds(prev => prev - 1);
11    }, 1000);
12  };
13
14  const stop = () => {
15    if (timerRef.current !== null) {
16      clearInterval(timerRef.current);
17      timerRef.current = null;
18    }
19  };
20
21  return (
22    <div>
23      <p>Odliczanie: {seconds}s</p>
24      <button onClick={start}>Start</button>
25      <button onClick={stop}>Stop</button>
26    </div>
27  );
28}
29
30// Poprzednia wartość
31const prevValueRef = useRef<string>("");

Typowe elementy HTML w useRef

1// Najczesciej używane typy elementów
2const inputRef = useRef<HTMLInputElement>(null);
3const textareaRef = useRef<HTMLTextAreaElement>(null);
4const selectRef = useRef<HTMLSelectElement>(null);
5const buttonRef = useRef<HTMLButtonElement>(null);
6const formRef = useRef<HTMLFormElement>(null);
7const divRef = useRef<HTMLDivElement>(null);
8const imgRef = useRef<HTMLImageElement>(null);
9const videoRef = useRef<HTMLVideoElement>(null);
Przejdź do CodeWorlds