Why Hooks?
Before Hooks (introduced in React 16.8), stateful logic lived only in class components. Hooks let you use state and other React features in function components, making code shorter, more reusable, and easier to test.
useState
useState is the most fundamental Hook. It returns a stateful value and a setter function:
const [count, setCount] = useState(0);
// Update: setCount(count + 1) or setCount(prev => prev + 1)
useEffect
useEffect runs side effects after render. Control when it fires with the dependency array:
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]); // runs whenever count changes
Return a cleanup function to cancel subscriptions or timers when the component unmounts.
useContext
Share values deeply without prop-drilling. Create a context, wrap a subtree with its Provider, and consume it with useContext(MyContext).
useReducer
Prefer useReducer over useState when state transitions are complex or depend on the previous state:
const [state, dispatch] = useReducer(reducer, initialState);
dispatch({ type: 'INCREMENT' });
useCallback and useMemo
These memoisation hooks prevent unnecessary re-renders of child components and expensive re-computations. Use them judiciously — premature optimisation adds complexity.
Custom Hooks
Extract reusable stateful logic into custom Hooks (functions whose names start with use). Examples: useFetch, useLocalStorage, useDebounce.
Conclusion
React Hooks have fundamentally changed how we write components. Mastering them unlocks cleaner code and better component architecture across any React codebase.