A genuinely common point of confusion involves a developer noticing their component’s render logic, or a useEffect, executing twice in development mode, assuming this indicates a bug or performance problem, when this is actually intentional behavior from React’s Strict Mode specifically designed to help surface certain categories of bugs during development.


What Strict Mode Actually Does

Strict Mode is a development-only tool that intentionally double-invokes certain functions — component render functions and some effect functions — specifically to help detect side effects that are not properly cleaned up or that incorrectly assume they will only run once. This double-invocation does not occur in production builds, meaning this is genuinely a development-time diagnostic behavior, not a performance characteristic that affects your actual deployed application.

<React.StrictMode>
  <App />
</React.StrictMode>

Why Double-Invoking Renders Helps Catch Bugs

If your component’s render logic has side effects that should not occur during rendering (modifying external variables, triggering effects directly within render rather than in useEffect), double-invoking the render function in development makes these kinds of impure render side effects more likely to become visibly apparent — perhaps producing visibly incorrect duplicated behavior — compared to a single invocation where such issues might not be immediately obvious.

This connects to a fundamental React principle: render functions should be pure, producing the same output given the same input without causing external side effects. Strict Mode’s double rendering specifically helps verify this purity assumption holds for your actual component code, surfacing violations during development before they potentially cause subtler issues in production.


Why Effects Also Double-Invoke

Beyond render functions, Strict Mode also double-invokes effect setup and cleanup functions specifically to help verify that your effect cleanup logic correctly and completely reverses whatever the effect setup did, which matters genuinely for avoiding subtle bugs related to effects that do not clean up properly when a component unmounts and potentially remounts (which can happen for various reasons beyond simple removal from the page).

useEffect(() => {
  const subscription = subscribeToSomething();
  return () => subscription.unsubscribe();
}, []);

If your cleanup function does not properly reverse everything your setup function did, Strict Mode’s double-invocation in development (setup, cleanup, setup again) is specifically designed to make resulting bugs (like duplicate subscriptions, since the second setup ran without the first one’s effects being fully reversed) more likely to become visibly apparent during development testing, rather than only surfacing unpredictably in production under specific conditions that might not be tested as thoroughly.


Confirming This Is Strict Mode and Not a Genuine Performance Problem

If you are seeing double execution and want to confirm this is genuinely Strict Mode’s intentional behavior rather than an actual bug, checking whether your application is wrapped in <React.StrictMode>, and confirming whether the doubled behavior disappears in a production build (where Strict Mode’s double-invocation does not occur), helps verify this distinction directly rather than assuming either explanation without checking.


Why You Should Not Disable Strict Mode Just to Stop the Double Rendering

Given that this double-invocation does not affect your actual production behavior or performance, disabling Strict Mode specifically to make the development-time double rendering disappear removes a genuinely useful diagnostic tool without providing any actual production benefit, since production builds were never affected by this double-invocation in the first place.

If your effect or render logic produces visibly incorrect behavior under Strict Mode’s double-invocation, this is specifically surfacing a genuine underlying issue (improper cleanup, impure render side effects) that exists in your code regardless of whether Strict Mode happens to make it visible, and the appropriate fix is addressing that underlying issue directly, rather than disabling the diagnostic tool that happened to reveal it.


A Genuine Example of a Bug Strict Mode Helped Surface

I encountered a case where an effect was setting up an interval timer without properly clearing it in the cleanup function. Under normal single-invocation behavior, this issue might not have been immediately obvious in casual testing, but Strict Mode’s double-invocation in development caused two separate intervals to run simultaneously, producing a visibly incorrect doubled update frequency that made the missing cleanup considerably more apparent than it might have been otherwise, leading directly to identifying and fixing the actual missing cleanup logic.

// Buggy: missing cleanup means Strict Mode reveals duplicate intervals
useEffect(() => {
  const interval = setInterval(() => updateSomething(), 1000);
  // Missing: return () => clearInterval(interval);
}, []);

Distinguishing Strict Mode Behavior From Genuine Re-Render Performance Issues

This distinction matters for correctly interpreting what you observe during development. The render-count and performance-related guidance covered throughout our other articles on this site concerns genuine re-render patterns that also occur in production and that profiling tools like React DevTools Profiler are measuring. Strict Mode’s development-only double-invocation is a separate, distinct phenomenon specifically for bug detection, not a performance characteristic that the Profiler’s production-relevant measurements are concerned with capturing or that you need to optimize away.


A Quick Reference Summary

Observation Explanation
Double render/effect execution in development only Strict Mode’s intentional diagnostic behavior
Visible duplicate side effects (subscriptions, intervals) under this double-invocation Likely reveals a genuine cleanup or purity bug worth fixing
Same double execution appearing in production build Not Strict Mode — investigate as a genuine separate issue
Disabling Strict Mode to stop development double-rendering Removes useful diagnostic without any actual production benefit

What This Understanding Changed

Once I could explain that Strict Mode’s double-invocation is intentional and development-only, conversations about “fixing” this behavior shifted toward the more genuinely useful question of whether the double-invocation was revealing an actual underlying bug worth addressing, which is precisely the diagnostic purpose this tool is designed to serve, rather than treating the double-invocation itself as the problem requiring a fix.

Are you seeing unexpected double execution in your application? Describe what you are observing and I can help you think through whether this reflects Strict Mode’s intentional behavior or a genuinely separate issue.