useState
const [count, setCount] = useState(0);
const [user, setUser] = useState<User | null>(null);
// Update based on previous value
setCount(prev => prev + 1);
// Object state
setUser(prev => ({ ...prev, name: 'Alice' }));
useEffect
// Run on every render
useEffect(() => { console.log('rendered'); });
// Run once (mount)
useEffect(() => { fetchData(); }, []);
// Run when deps change
useEffect(() => { fetchUser(id); }, [id]);
// Cleanup
useEffect(() => {
const timer = setInterval(tick, 1000);
return () => clearInterval(timer); // Cleanup on unmount
}, []);
useRef
const inputRef = useRef<HTMLInputElement>(null);
// Access DOM
inputRef.current?.focus();
// Mutable value (doesn't trigger re-render)
const renderCount = useRef(0);
renderCount.current++;
useMemo & useCallback
// Memoize expensive computation
const sorted = useMemo(() =>
items.toSorted((a, b) => a.price - b.price),
[items]
);
// Memoize callback (prevent child re-renders)
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
useContext
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
);
}
function Child() {
const theme = useContext(ThemeContext); // 'dark'
}
Custom Hook
function useLocalStorage<T>(key: string, initial: T) {
const [value, setValue] = useState<T>(() => {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : initial;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue] as const;
}