A
AiTechWorlds
AiTechWorlds
useState, useEffect, useContext, useRef, useMemo every hook explained with real examples.

import { useState } from 'react';
// Basic state
const [count, setCount] = useState(0);
const [name, setName] = useState('');
const [user, setUser] = useState<User | null>(null);
// Functional update (when new state depends on old)
setCount(prev => prev + 1);
// Object state โ always spread, never mutate!
const [form, setForm] = useState({ name: '', email: '' });
setForm(prev => ({ ...prev, name: 'Alice' }));
// Lazy initialization (expensive initial state)
const [data, setData] = useState(() => computeExpensiveValue());import { useEffect } from 'react';
// Run after every render
useEffect(() => {
console.log("rendered");
});
// Run once (on mount)
useEffect(() => {
fetchData();
}, []);
// Run when dependencies change
useEffect(() => {
fetchUser(userId);
}, [userId]);
// Cleanup (unsubscribe, clear timers)
useEffect(() => {
const id = setInterval(() => tick(), 1000);
return () => clearInterval(id); // cleanup function
}, []);
// Async in useEffect
useEffect(() => {
let cancelled = false;
async function load() {
const data = await fetchData();
if (!cancelled) setData(data);
}
load();
return () => { cancelled = true; };
}, [id]);import { useRef } from 'react';
// DOM reference
const inputRef = useRef<HTMLInputElement>(null);
// In JSX: <input ref={inputRef} />
inputRef.current?.focus();
// Mutable value (no re-render on change)
const timerRef = useRef<NodeJS.Timeout | null>(null);
timerRef.current = setTimeout(() => {}, 1000);
// Previous value pattern
function usePrevious<T>(value: T) {
const ref = useRef<T>();
useEffect(() => { ref.current = value; });
return ref.current;
}import { createContext, useContext, useState } from 'react';
// 1. Create context
interface ThemeContextType {
theme: 'light' | 'dark';
toggle: () => void;
}
const ThemeContext = createContext<ThemeContextType | null>(null);
// 2. Provide context (wrap your app or section)
function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
const toggle = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme, toggle }}>
{children}
</ThemeContext.Provider>
);
}
// 3. Use context in any child component
function ThemedButton() {
const ctx = useContext(ThemeContext);
if (!ctx) throw new Error("Must be inside ThemeProvider");
return <button onClick={ctx.toggle}>Mode: {ctx.theme}</button>;
}import { useMemo, useCallback } from 'react';
// useMemo โ memoize expensive computation
const sortedList = useMemo(
() => [...items].sort((a, b) => a.name.localeCompare(b.name)),
[items] // recalculate only when items changes
);
// useCallback โ memoize function reference
const handleClick = useCallback(
(id: number) => {
deleteItem(id);
refetch();
},
[refetch] // new function only when refetch changes
);When to use:
useMemo Expensive calculations, avoid unnecessary re renders of pure componentsuseCallback Passing callbacks to optimized child components wrapped in React.memoimport { useReducer } from 'react';
type State = { count: number; error: string | null };
type Action =
| { type: 'increment' }
| { type: 'decrement' }
| { type: 'reset' }
| { type: 'setError'; payload: string };
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'increment': return { ...state, count: state.count + 1 };
case 'decrement': return { ...state, count: state.count - 1 };
case 'reset': return { count: 0, error: null };
case 'setError': return { ...state, error: action.payload };
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0, error: null });
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}// useFetch โ data fetching hook
function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
let cancelled = false;
setLoading(true);
fetch(url)
.then(r => r.json())
.then(d => { if (!cancelled) setData(d); })
.catch(e => { if (!cancelled) setError(e.message); })
.finally(() => { if (!cancelled) setLoading(false); });
return () => { cancelled = true; };
}, [url]);
return { data, loading, error };
}
// useLocalStorage โ sync state with localStorage
function useLocalStorage<T>(key: string, initial: T) {
const [value, setValue] = useState<T>(() => {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initial;
} catch { return initial; }
});
const setStored = (newValue: T) => {
setValue(newValue);
localStorage.setItem(key, JSON.stringify(newValue));
};
return [value, setStored] as const;
}eslint plugin react hooks enforces these rules automatically| Hook | Purpose |
|---|---|
| useState | Local component state |
| useEffect | Side effects, subscriptions |
| useRef | DOM refs, mutable values |
| useContext | Global state consumption |
| useMemo | Memoize computed values |
| useCallback | Memoize function references |
| useReducer | Complex state with actions |
| useId | Unique IDs for accessibility |
| useTransition | Mark updates as non urgent |
| useDeferredValue | Defer expensive re renders |
Get more notes like this daily on Telegram!
Free study notes, cheat sheets & AI tips
Last reviewed on June 13, 2026 by the AiTechWorlds Notes Team. Free cheat sheet no signup required.
Join AiTechWorlds on Telegram and get daily AI tips, prompt engineering templates, coding resources, and exclusive content 100% free!
No spam. Leave anytime.