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
ReactJune 23, 20264 min read

React Rendering: Why Your Logic Must Be Idempotent

Master React rendering by keeping your logic idempotent. Learn why side effects in your JSX cause bugs and how to separate concerns for predictable code.

ReactFrontend EngineeringWeb DevelopmentJavaScriptHooksNext.jsTutorial

I remember sitting at my desk three years ago, staring at a console log that fired exactly four times whenever a user clicked a button. I was convinced my component was broken, but the truth was more subtle: I had violated the fundamental rules of the render phase. If you want to move from writing "code that works" to "code that’s maintainable," you have to stop treating your JSX like a dumping ground for logic.

When we talk about React rendering, we aren't just talking about updating the DOM. We’re talking about a pure function execution that React can call multiple times, often in rapid succession. If you put side effects—like API calls, random number generation, or modifying global variables—directly into your function body, you’re playing with fire.

The Problem with "Render-Phase" Side Effects

In a perfect world, a component is a pure function: UI = f(state, props). Given the same state and props, it should produce the exact same JSX every single time. When you introduce logic that isn't idempotent, you break this contract.

I once saw a junior developer try to fetch data directly inside a component body:

JAVASCRIPT
function UserProfile({ userId }) {
  // DON'T DO THIS
  const [user, setUser] = useState(null);
  fetch(CE9178">`/api/user/${userId}`).then(res => res.json()).then(setUser);
  
  return <div>{user?.name}</div>;
}

This code is a nightmare. Because the fetch happens during the render phase, every time the component re-renders—perhaps due to a parent update—it fires another network request. It creates an infinite loop of state updates and renders that can crash a browser tab in seconds.

Why Idempotency Matters

Idempotence means that performing an operation once has the same effect as performing it multiple times. If your component logic is idempotent, React can safely call your function whenever it needs to calculate the UI. This is the heart of React rendering: Mastering State Batching and the Two-Pass Model.

If you’re struggling with why your variables seem to "reset" or why your component updates unexpectedly, it’s usually because you haven't fully grasped the React state snapshot mental model. Each render captures its own version of props and state. If you try to mutate things outside that scope, you’ll fight the framework instead of working with it.

Moving Logic Out of JSX

To write clean, predictable components, you need to follow a few React best practices:

  1. Keep the component body pure: Use it only to calculate values based on state and props.
  2. Move side effects to hooks: Use useEffect or event handlers for anything that interacts with the "outside world."
  3. Use useMemo and useCallback sparingly: Only use them when you actually need to optimize performance, not to "fix" impure logic.

If you find yourself needing to track values that don't trigger a re-render, look into how React useRef and Component Memory: Why Variables Reset on Re-render works. It’s often the missing piece for developers who try to force state into variables that shouldn't be stateful.

A Better Way to Handle Logic

Instead of putting logic in the render path, extract it. If you have complex calculations, move them into helper functions outside the component. If you have data fetching, use a library like TanStack Query or at least wrap your fetch in a useEffect.

Here is the robust approach:

JAVASCRIPT
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    let active = true;
    fetch(CE9178">`/api/user/${userId}`)
      .then(res => res.json())
      .then(data => {
        if (active) setUser(data);
      });
    return () => { active = false; };
  }, [userId]); // Only runs when userId changes
  
  return <div>{user?.name || "Loading..."}</div>;
}

By isolating the side effect inside useEffect, we ensure the component stays predictable. We also handle the "cleanup" phase, which is a common source of bugs in complex apps. Understanding this flow is vital when you start looking at React Purity and Side Effects: Building Predictable UI Components.

What I Still Get Wrong

I’ll be honest: I still catch myself writing "quick and dirty" logic inside a component body when I’m prototyping. Then, I run into a weird bug where a modal opens twice or a counter jumps by two instead of one. It’s a humbling reminder that React’s engine is smarter than my shortcuts.

Next time you’re debugging, ask yourself: "If this function ran three times right now, would the outcome change?" If the answer is yes, you’ve found your bug. Don't fight the render phase; respect it, and your UI will be significantly more stable.

Back to Blog

Similar Posts

ReactNext.jsJune 23, 20265 min read

React Purity and Side Effects: Building Predictable UI Components

Master React purity to build predictable UI. Learn how functional programming in React keeps your components bug-free and easy to maintain as your app grows.

Read more
ReactNext.js
June 22, 2026
4 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.

Read more
ReactNext.jsJune 22, 20264 min read

React reconciliation and component state persistence: A mental model

React reconciliation determines how component state persistence works during re-renders. Learn how React Fiber maintains your UI state across cycles.

Read more