React calls your API twice in development because StrictMode intentionally double-invokes effects and component functions to surface bugs. In production builds, this does not happen; the duplicate call is a development-only behavior that you can stop by removing StrictMode or by writing an idempotent cleanup in your effect.
Background: Why StrictMode Exists
React’s StrictMode is a development tool that helps you find problems before they reach users. It was introduced in React 16.3 as a way to opt into extra checks and warnings. One of its key behaviors is double-invoking certain functions: the component body, state updater functions, and useEffect callbacks. This is not a bug—it is a deliberate feature.
The double-invocation is designed to make your code resilient to unmounting and remounting, which happens in real apps when a user navigates away and back, or when a component’s position in the tree changes. By running your effect twice, StrictMode forces you to notice if you are relying on side effects happening only once. If your API call is not idempotent (that is, calling it twice produces a different result), you will see the problem immediately in development instead of in production.
How StrictMode Triggers the Double Call
When you wrap your app in <React.StrictMode>, React runs the following in development only:
- It mounts the component, runs the effect, then immediately unmounts it (simulating a cleanup).
- It remounts the component and runs the effect again.
This means your useEffect with an API call like fetch('/api/data') will fire twice in the console. The same happens for useMemo, useReducer, and the render function itself. In production, StrictMode does nothing—it is a no-op. So the duplicate call only appears when you run npm start or yarn dev.
What Actually Stops the Double Call
There are several ways to prevent the duplicate request, depending on your goal.
Option 1: Remove StrictMode (Not Recommended)
You can simply delete <React.StrictMode> from your index.js or main.jsx. This stops the double invocation immediately. However, you lose the safety net that catches other bugs like impure renders or missing cleanup. Most developers keep StrictMode and fix their code instead.
Option 2: Write a Proper Cleanup Function
The recommended approach is to make your effect safe to run twice. In useEffect, you can return a cleanup function that cancels the first request before the second one starts. For example:
useEffect(() => {
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(res => res.json())
.then(setData);
return () => controller.abort();
}, []);
With an AbortController, the first fetch is aborted when the cleanup runs, so only the second request actually completes. This is the cleanest solution because it also handles unmounting during navigation.
Option 3: Use a Ref or Module-Level Flag
If you cannot cancel the request (e.g., you are using a library that does not support abort), you can use a useRef to track whether the effect has already run:
const didFetch = useRef(false);
useEffect(() => {
if (didFetch.current) return;
didFetch.current = true;
fetch('/api/data').then(...);
}, []);
This works because the ref persists across the simulated unmount/remount. However, it is a bit hacky and does not help with cleanup on real unmounts. Use it only when you have no other option.
Common Misconceptions
Many developers think the double call is caused by React Router, by the browser, or by their own code. In reality, it is almost always StrictMode. Another misconception is that the double call happens in production—it does not. You can verify this by building your app (npm run build) and serving it; the API will be called once.
Some also believe that the double call is a performance problem. It is not a performance issue in development because it only runs once per mount, and the second request is often aborted. The real risk is that you might accidentally send a POST request twice, which could create duplicate records. That is exactly why StrictMode forces you to handle it.
How to Verify the Cause
If you are not sure whether StrictMode is the culprit, do this:
- Open your browser’s Network tab.
- Refresh the page and watch the API request.
- If you see two identical requests, temporarily remove
<React.StrictMode>from your entry file. - Refresh again. If only one request appears, StrictMode was the cause.
You can also check the React DevTools—StrictMode shows a special icon in the component tree.
Alternatives to StrictMode
If you are using a framework like Next.js or Remix, StrictMode is often enabled by default. You can disable it in next.config.js or remix.config.js, but again, it is not recommended. Some teams use a custom hook that debounces or deduplicates API calls, but that is overkill for a development-only issue. The simplest alternative is to keep StrictMode and adopt the cleanup pattern.
Frequently Asked Questions
Does StrictMode double-call in production?
No. StrictMode is a development-only wrapper. In a production build, it has no effect, and your API will be called exactly once. You can confirm by building your app and inspecting the network traffic.
Why does my POST request get sent twice?
If you are using useEffect to send a POST, StrictMode will trigger it twice in development. This can create duplicate records. The fix is to abort the first request or to use a ref to skip the second invocation. In production, it will only send once.
Is it safe to remove StrictMode?
It is safe in the sense that your app will work, but you lose valuable warnings about impure renders, legacy lifecycle methods, and other potential bugs. It is better to keep StrictMode and fix your code to handle the double invocation.
Does React Query or SWR double-fetch too?
Yes, if you use them inside a useEffect that is wrapped by StrictMode, they will also fire twice. However, these libraries often have built-in deduplication, so you might only see one network request. If you see two, use their deduplication options or abort the first request.
Will the double call happen if I use useCallback?
No. useCallback does not affect how many times the effect runs. The double call is caused by StrictMode remounting the component, regardless of how you memoize the callback.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Valheim Server Not Showing in Community List Fixes
- Soundbar vs 2.1 Speaker System: Which Is Better?
- DisplayPort vs HDMI: Which Cable Should You Use?
- Survive Lava for Brainrot Tier List170 points
- MySQL Dump Import: Fix Common Errors
- Mouse Moving on Its Own? Causes & Fixes