React 16.8 shipped Hooks in February 2019, and by early 2020 the React community has largely embraced them. Class components are not deprecated, but the momentum is clear: new code is written with function components and hooks. This guide covers the essential hooks and patterns every React developer needs to know.
useState: Local Component State
function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
</div>
);
}
Pass a function to setCount (rather than a value) when the new state depends on the previous state — it ensures you always work with the latest value even in async callbacks.
useEffect: Side Effects and Lifecycle
function UserProfile({ userId }) {
const [user, setUser] = React.useState(null);
React.useEffect(() => {
let cancelled = false;
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => { if (!cancelled) setUser(data); });
return () => { cancelled = true; }; // cleanup
}, [userId]); // re-run when userId changes
return user ? <h1>{user.name}</h1> : <p>Loading...</p>;
}
useCallback and useMemo: Memoisation
useCallback memoises a function reference. useMemo memoises a computed value. Both accept a dependency array and only recompute when dependencies change — preventing unnecessary re-renders in child components that receive these as props.
useRef: Persistent Mutable Values
useRef gives you a mutable container that persists across renders without triggering re-renders when changed. It’s commonly used to hold DOM element references and timer IDs.
Custom Hooks: Reusable Logic
Any function that calls other hooks and starts with use is a custom hook. Extract shared logic into custom hooks to keep components clean:
function useFetch(url) {
const [data, setData] = React.useState(null);
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
fetch(url)
.then(r => r.json())
.then(d => { setData(d); setLoading(false); });
}, [url]);
return { data, loading };
}
// In a component:
const { data, loading } = useFetch('/api/posts');
Rules of Hooks
- Only call hooks at the top level — never inside loops, conditions, or nested functions
- Only call hooks from React function components or custom hooks
Hooks make complex React components dramatically simpler and dramatically easier to test. Learning them thoroughly is the most important React skill investment you can make in 2020.