JavaScript & React

React Hooks: Rethinking State Management in Functional Components

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.

Share this post:
Copied!

Leave a Comment

Your email will not be published.

READY TO BUILD?

Let's Build Something
Amazing Together

Tell us about your project. We'll have a proposal in your inbox within 24 hours.

Free Consultation
NDA Available
Fixed-price Options
Dedicated PM