From Blaze to Next.js: My 10-Year Journey to Mastering React State
I’ve spent the last decade jumping between frameworks like a digital nomad seeking the perfect home. I’ve lived through the rigid architecture of Angular, the approachable elegance of Vue, and even the "old-school" magic of Blaze. Each had its charm, but they always felt like they were fighting me once the codebase got heavy. Then I found React. It wasn't just a library; it was a mental shift. Today, I build high-scale systems using React within the Meteor ecosystem for real-time power and Next.js for that surgical SEO precision.
This journey taught me that while frameworks are tools, Hooks are the actual craftsmanship. They are the reason I stopped wrestling with the DOM and started actually engineering. Here is how I use them to keep my sanity in the trenches.
Look, I’ve spent the last decade in the trenches of frontend engineering. I’ve seen React go from "that weird library from Facebook with the HTML-in-JS syntax" to the absolute juggernaut it is today. I’ve lived through the era of Class Components, the nightmare of Higher-Order Components, and the "Render Props" craze.
But nothing, and I mean NOTHING, changed the game like the introduction of Hooks.
If you’re looking at the infographic above and thinking, "Yeah, I know useState, I'm good," you’re missing the forest for the trees. Mastering hooks isn't about memorizing the API; it’s about shifting your entire mental model of how data flows through an application. It's about writing code that doesn't just work, but stays maintainable when your team scales from two developers to fifty.
Here is the truth: A senior developer isn't someone who uses every hook. A senior developer is someone who knows which hook to use and, more importantly, when to stay far away from them.

1. The Foundation: useState and useReducer
Every developer starts with useState. It’s the first hit of power you get. But successful developers know where its limits lie.
When to use useState: It’s perfect for local, independent pieces of state. A toggle for a modal, the text in a search bar, or a simple counter. It’s clean, it’s fast, and it’s easy to reason about.
When NOT to use it: The moment you find yourself with five or six useState calls that all depend on each other, you’ve entered "State Synchronization Hell." If updating setLoading always requires updating setError and setData, you’re asking for bugs.
The Move to useReducer: This is where the "serious" developers live. useReducer is essentially a local Redux. It’s for complex state logic where the next state depends on the previous one.
Example: A multi-step checkout form. You have shipping info, payment info, and cart validation. Instead of five useStates, use a reducer. It centralizes your logic, making it much easier to test and debug. You dispatch an "action," and the reducer handles the "how." It’s predictable. Predictability is the hallmark of a senior dev.

2. The Heavy Lifter: useEffect
If I had a dollar for every "Infinite Loop" caused by a poorly written useEffect, I’d be retired on a beach. This is the most misunderstood hook in the entire library.
The Philosophy: useEffect isn't a lifecycle method. Stop trying to treat it like componentDidMount. It’s a tool for synchronization. It synchronizes your React component with something outside of React, like an API, a websocket, or the browser’s localStorage.
When to use it: Fetching data on a page load, setting up a subscription to a chat service, or triggering a manual DOM animation that React can’t handle declaratively.
When NOT to use it: Do not use useEffect to transform data. If you have a list of users and you want to filter them based on a search term, do not put that filtering logic in an effect. Just do it in the body of the component.
Bad: useEffect(() => { setFilteredUsers(users.filter(u => u.name.includes(term))) }, [term, users])
Good: const filteredUsers = users.filter(u => u.name.includes(term))
The second one is faster, uses less memory, and is way easier to read.
3. The Performance Duo: useMemo and useCallback
This is where people get obsessive. I see juniors wrapping every single function in useCallback. Stop it. You’re making your code harder to read for almost zero performance gain.
The Reality Check: Every hook has a cost. React has to store that function or value in memory and check the dependency array on every single render. If your function is just a simple math calculation or a small array filter, the overhead of the hook is often "heavier" than the cost of just re-creating the function.
When to use useMemo: Use it for truly "expensive" operations. If you’re processing 5,000 rows of data or doing complex data visualization math, useMemo is a lifesaver.
When to use useCallback: There is really only one primary reason to use useCallback: Referential Integrity. If you are passing a function down to a child component that is wrapped in React.memo, that child will re-render every time the parent re-renders unless the function's reference stays the same. That’s when you wrap it. Otherwise, you're just adding noise to your codebase.
4. The Hidden Power: useRef
Most people think useRef is just for grabbing a DOM element to focus an input. That’s like using a Ferrari to go to the grocery store.
The Secret Weapon: useRef is an "instance variable" for functional components. It holds a value that persists across renders but does not trigger a re-render when it changes.
When to use it: Storing a timer ID for setInterval, keeping track of the "previous" props to compare them, or managing a third-party library (like a map or a chart) that needs a stable reference. It’s the "escape hatch" when you need to step outside the reactive flow.
5. Context and useContext: The "Prop Drilling" Killer
We’ve all been there. Passing a user object through five layers of components just because the footer needs to show the username. It’s soul-crushing.
useContext is the solution, but it’s a double-edged sword.
When to use it: Global data. Themes (Dark/Light mode), User Authentication state, Language settings. Things that truly the entire app needs to know about.
The Trap: Do not use Context for high-frequency updates. If you put a "timer" or a "scroll position" in a Context Provider, every single component consuming that context will re-render every time the value changes. It can absolutely tank your app's performance. For high-frequency state, stick to local state or a dedicated state management library like Zustand or Jotai.
6. The "Pro" Level: Custom Hooks
This is the peak of React development. If you aren't writing custom hooks, you aren't really using React to its full potential.
A custom hook is just a function that starts with "use" and calls other hooks. But the power it gives you is immense. It allows you to separate your Business Logic from your UI Logic.
The Pattern: I like to keep my components "dumb." They should just take data and render it. All the fetching, the error handling, the debouncing, and the state management should live in a custom hook.
Example: Instead of having 40 lines of useEffect and useState inside a UserProfile component, I write const { user, loading, error } = useUser(userId);.
Now, I can reuse useUser in the Navbar, the Settings page, and the Sidebar. If I decide to switch from REST to GraphQL, I only have to change the code in one file. That is how you build an enterprise-grade app.
Why This Makes You a "Serious" Developer
The world is full of "tutorial devs" who can copy-paste a useState hook. But companies aren't hiring for that anymore. They are hiring for people who can prevent technical debt.
When you understand the nuances of these hooks:
- You write less code. (And the best code is the code you don't have to write).
- Your bugs are easier to find. Because your logic is modular and predictable.
- Your apps are fast. Not because you optimized everything, but because you knew what not to over-optimize.
- You are a better teammate. Your code is readable. Someone else can jump into your component and understand the "intent" behind your state management within seconds.
The Final Word
Look at that infographic again. Don't just look at the code snippets—look at the "Why Hooks?" section.
- Reusing stateful logic.
- Cleaner, shorter components.
- Better performance patterns.
These aren't just bullet points; they are the KPIs of your career. If your components are getting long, you’ve failed the "Cleaner" goal. If you’re copy-pasting logic, you’ve failed the "Reusing" goal.
React isn't about the library; it's about the architecture. Hooks are the tools that let you build that architecture with surgical precision. Stop "coding" and start "engineering." Learn the hooks, respect their limits, and build something that doesn't break the moment you turn your back on it.
That’s what it means to be a successful React developer. Now go get to work.


