Mahamudul Hasan Rubel
HomeAboutProjectsSkillsExperienceBlogPhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
ReactNext.jsJune 22, 20264 min read

React derived state: Stop using useEffect for data calculations

React derived state is the key to faster components. Learn how to stop abusing useEffect for data transformations and simplify your React performance optimization.

ReactPerformanceFrontendJavaScriptHooksWeb DevelopmentNext.jsTutorial

During a recent production audit, I found a dashboard component that was re-rendering four times for every single user input. The culprit wasn't complex logic; it was a developer trying to "sync" state using useEffect every time the source data changed.

If you’re reaching for useEffect to transform or filter data before displaying it, you’re likely creating a performance bottleneck. Let’s look at how to fix this by shifting your mental model toward pure calculation during the render phase.

The Problem with Synchronizing State

We often fall into the trap of treating useEffect like a lifecycle method from the Class component era. We think: "When props.items changes, I need to update filteredItems." So, we write this:

JAVASCRIPT
const [items, setItems] = useState([]);
const [filteredItems, setFilteredItems] = useState([]);

useEffect(() => {
  setFilteredItems(items.filter(item => item.active));
}, [items]);

This is a classic anti-pattern. When items changes, React renders the component, runs the effect, and then triggers another render to update filteredItems. You’ve just doubled the work for the browser. This creates cascading re-renders that make your UI feel sluggish, especially on low-end mobile devices.

Understanding how React rendering: Mastering State Batching and the Two-Pass Model works is crucial here. When you update state inside an effect, you force React to go back to the top of the component tree, wasting cycles on a second pass.

Refactoring to React Derived State

Instead of storing derived data in state, calculate it on the fly. Since your component function re-runs every time props or state change, you can perform the calculation directly in the component body.

JAVASCRIPT
function ItemList({ items }) {
  // Calculate directly during render
  const filteredItems = items.filter(item => item.active);

  return (
    <ul>
      {filteredItems.map(item => <li key={item.id}>{item.name}</li>)}
    </ul>
  );
}

This approach is faster, cleaner, and removes the need for manual synchronization. By leveraging React reconciliation and component state persistence: A mental model, you ensure that your UI always reflects the current source of truth without unnecessary intermediate states.

When Should You Use useMemo?

A common follow-up question I get from juniors is: "Won't this slow down the app if the calculation is expensive?"

If you are performing heavy operations—like sorting a list of 5,000 items—then yes, you should wrap the calculation in useMemo. But don't use it prematurely. Start by calculating directly in the body. If your browser performance tools show a drop in frame rate, then optimize.

Remember, useEffect is a synchronization tool, not state management. It’s for talking to the outside world—APIs, DOM manipulation, or subscriptions—not for managing internal data flow.

Why This Matters for React Performance Optimization

When you move logic out of useEffect, you reduce the mental overhead of tracking "what updates what." You stop worrying about infinite loops caused by dependency arrays. You also make your components easier to test because they become pure functions of their inputs.

If you're working in a Next.js rendering environment, this becomes even more critical. Server components and client components interact in ways that make "double-render" bugs harder to debug. Keeping your data flow predictable ensures that your hydration phase doesn't produce those dreaded "text content did not match" errors.

Common Pitfalls

  1. The "Shadow State" Trap: Don't keep a useState variable if it’s just a copy of a prop. Just use the prop directly.
  2. Missing Dependencies: If you must use useEffect for actual side effects, make sure your dependency array is exhaustive. If you're struggling with React State Synchronization: How to Avoid Infinite Loops, it’s almost always a sign that you should be using derived state instead.
  3. Over-optimizing: Don't wrap every filter or map in useMemo. Most JavaScript operations are incredibly fast; the cost of the useMemo hook itself can sometimes outweigh the benefit of skipping a simple calculation.

FAQ

Does calculating in the render body make my component slow? Generally, no. React is designed to run the component function repeatedly. Unless your calculation involves thousands of iterations or heavy parsing, you won't notice a difference.

What if I need to reset state when a prop changes? That is the only valid case for useEffect synchronization. Even then, consider using the key prop on your component to force a full re-mount rather than manually syncing state.

Is useMemo always better than just calculating the value? No. Only use it when the calculation is genuinely expensive. For simple arrays or strings, the overhead of the hook is often higher than the calculation itself.

Final Thoughts

I still catch myself writing useEffect for state updates when I'm tired or rushing through a feature. It’s a habit that’s hard to break. The key is to pause and ask: "Is this data derived from existing state?" If the answer is yes, delete the useEffect and calculate it during the render. Your users will appreciate the snappier interface, and your future self will thank you for the simpler code.

Back to Blog

Similar Posts

ReactNext.jsJune 22, 20264 min read

React useEffect: A Synchronization Tool, Not State Management

React useEffect is for synchronizing external systems, not state management. Learn why treating it as a lifecycle method leads to bugs and how to fix it.

Read more
ReactNext.js
June 22, 2026
4 min read

React keys and reconciliation: Why stable identity matters

React keys are essential for efficient reconciliation. Learn why stable component identity prevents UI bugs and performance bottlenecks when rendering lists.

Read more
A minimalist rendering of a white cube with a geometric pattern on a blue background.
ReactNext.jsJune 21, 20264 min read

React Rendering Lifecycle: Why Components Re-render and How to Optimize

Master the React rendering lifecycle to stop unnecessary updates. Learn why react re-renders happen and how to optimize your components for better performance.

Read more