React hooks are the engines of your spaceship. TypeScript lets you define what data flows through these engines, ensuring safe navigation.
The useState hook automatically infers the type from the initial value, but sometimes you need explicit typing:
1import { useState } from 'react';
2
3// Automatic type inference
4const [count, setCount] = useState(0); // number
5const [name, setName] = useState("Apollo"); // string
6const [active, setActive] = useState(true); // boolean
7
8// Explicit typing - needed when the initial value is null or undefined
9interface Planet {
10 id: number;
11 name: string;
12 type: string;
13}
14
15// State can be Planet or null
16const [selectedPlanet, setSelectedPlanet] = useState<Planet | null>(null);
17
18// Array of objects - empty array doesn't tell TypeScript about element type
19const [planets, setPlanets] = useState<Planet[]>([]);
20
21// Union types
22type Status = "idle" | "loading" | "success" | "error";
23const [status, setStatus] = useState<Status>("idle");1// 1. Initial value is null/undefined
2const [user, setUser] = useState<User | null>(null);
3
4// 2. Empty array
5const [items, setItems] = useState<string[]>([]);
6
7// 3. Union types with restricted values
8const [theme, setTheme] = useState<"dark" | "light">("dark");
9
10// 4. Complex object with optional fields
11interface FormData {
12 name: string;
13 email: string;
14 message?: string;
15}
16const [form, setForm] = useState<FormData>({ name: "", email: "" });The useRef hook is used to store references to DOM elements or values that don't cause re-rendering:
1import { useRef } from 'react';
2
3// Reference to a DOM element
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 may be null, so we use ?.
13 inputRef.current?.focus();
14 };
15
16 return (
17 <div>
18 <input ref={inputRef} placeholder="Search for a planet..." />
19 <button onClick={focusInput}>Focus</button>
20 </div>
21 );
22}useRef can also store any value that doesn't cause re-rendering:
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>Countdown: {seconds}s</p>
24 <button onClick={start}>Start</button>
25 <button onClick={stop}>Stop</button>
26 </div>
27 );
28}
29
30// Previous value
31const prevValueRef = useRef<string>("");1// Most commonly used element types
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);