Strict Mode in React JS
Strict Mode is a built-in React component that helps developers identify potential bugs, unsafe patterns, missing cleanup functions, and deprecated API usage during development. It performs additional checks on the components inside its tree without adding any visible UI of its own.
React JS Training: JustAcademy React JS Training Course
Course Demo: Register for React JS Course Demo
1. Learning Objectives
After completing this topic, you will be able to:
- Understand Strict Mode and its purpose in React.
- Enable Strict Mode for an entire application or a specific component tree.
- Understand why components may render more than once during development.
- Identify problems caused by impure rendering and missing Effect cleanup.
- Understand how Strict Mode checks callback refs.
- Recognize deprecated API warnings.
- Debug common Strict Mode issues and follow React best practices.
2. What Is Strict Mode?
Strict Mode is a development tool provided by React through the StrictMode component. It enables additional checks that help developers discover mistakes before an application reaches production.
Strict Mode does not create a visible HTML element or change the application's design. Instead, it checks the behavior of components inside its boundaries.
Key Characteristics
- It is imported from the React package.
- It can wrap the entire application or part of a component tree.
- It performs extra checks in development mode.
- It helps identify impure rendering logic.
- It checks whether Effects and callback refs clean up correctly.
- It helps identify deprecated React APIs.
- Its extra checks do not affect the production build.
Important: Strict Mode is not a replacement for testing, linting, or error handling. It is an additional development aid.
3. Why Is Strict Mode Important?
React applications can contain bugs that are difficult to notice during normal rendering. For example, a component may accidentally modify an array received through props, create duplicate subscriptions, or leave an event listener active after a component is removed.
Strict Mode makes these problems easier to detect by deliberately repeating certain operations during development.
Benefits of Strict Mode
- Early bug detection: Reveals potential issues while developing.
- Pure rendering: Helps identify components that modify external data during rendering.
- Effect cleanup: Reveals subscriptions, timers, or connections that are not cleaned up.
- Ref cleanup: Helps identify callback refs that leave stale references behind.
- Code quality: Encourages predictable and maintainable React components.
- API compatibility: Warns about certain deprecated APIs.
4. How to Enable Strict Mode
You can enable Strict Mode by wrapping your React component tree with the component.
Example: main.jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
createRoot(document.getElementById("root")).render(
<StrictMode>
<App />
</StrictMode>
);
Explanation
- Import
StrictMode from React.
- Import
createRoot from React DOM.
- Create the React root using the HTML element with the ID
root.
- Wrap the root application component with
.
- React performs the additional development checks on the components inside this boundary.
Enabling Strict Mode for a Specific Section
Strict Mode can also be used for only part of an application.
import { StrictMode } from "react";
import Header from "./Header";
import Dashboard from "./Dashboard";
import Footer from "./Footer";
export default function App() {
return (
<>
<Header />
<StrictMode>
<Dashboard />
</StrictMode>
<Footer />
</>
);
}
In this example, the extra Strict Mode checks apply to Dashboard and its descendants, but not to Header or Footer.
5. What Does Strict Mode Check?
React's current Strict Mode checks include the following development-only behaviors:
| Check |
Purpose |
| Extra rendering |
Helps identify impure component rendering and state-related calculations. |
| Extra Effect setup and cleanup cycle |
Helps reveal missing cleanup for subscriptions, timers, and connections. |
| Extra callback ref setup and cleanup cycle |
Helps reveal stale or leaked DOM references. |
| Deprecated API checks |
Warns about certain deprecated React APIs. |
These checks are designed to help identify bugs that may also cause problems in production under certain conditions.
6. Strict Mode and Double Rendering
One of the most noticeable Strict Mode behaviors is that React calls a component's render logic an extra time in development to help detect impure code. This does not mean that every event handler is executed twice.
Example: Component Rendering
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
function Greeting() {
console.log("Greeting rendered");
return <h1>Hello, React!</h1>;
}
function App() {
return (
<StrictMode>
<Greeting />
</StrictMode>
);
}
createRoot(document.getElementById("root")).render(<App />);
In development, you may see the render log more than once because Strict Mode intentionally invokes render logic an extra time. The exact logs depend on the rendering setup and React version.
Why Does React Do This?
React components should be pure: given the same props, state, and context, their rendering logic should produce the same JSX without modifying external data.
If rendering changes an external array, increments a global variable, or performs another unintended side effect, the extra invocation makes the mistake easier to detect.
7. Pure and Impure Components
A pure component's rendering logic does not modify external data or produce unintended side effects. An impure component may change data outside itself while rendering, causing inconsistent results.
Example of Impure Rendering
function StoryList({ stories }) {
stories.push({
id: "new-story",
title: "Create Story"
});
return (
<ul>
{stories.map(story => (
<li key={story.id}>{story.title}</li>
))}
</ul>
);
}
Problem: The component directly modifies the array received through props. Every render may add another item to the original array.
Correct Approach
function StoryList({ stories }) {
const items = [
...stories,
{
id: "new-story",
title: "Create Story"
}
];
return (
<ul>
{items.map(story => (
<li key={story.id}>{story.title}</li>
))}
</ul>
);
}
Explanation: The spread operator creates a new array. The component no longer changes the original array, so repeated rendering does not accumulate duplicate items.
Pure vs Impure Rendering
| Pure Rendering |
Impure Rendering |
| Does not modify props. |
Modifies props or external data. |
| Calculates JSX from inputs. |
Produces unintended side effects while rendering. |
| Behaves predictably when invoked again. |
May produce different results on repeated invocation. |
| Works well with React's rendering model. |
Can cause duplicate data or unpredictable UI. |
8. Strict Mode and useEffect
The useEffect() Hook is used to synchronize a component with an external system, such as a subscription, timer, browser event listener, or network connection.
In development, Strict Mode runs an additional Effect setup and cleanup cycle on initial mounting when the relevant Strict Mode boundary is at the root. This helps identify Effects that do not clean up correctly.
Example of an Effect Without Cleanup
import { useEffect } from "react";
function Timer() {
useEffect(() => {
const timerId = setInterval(() => {
console.log("Timer running");
}, 1000);
}, []);
return <h2>Timer Example</h2>;
}
export default Timer;
Problem: The interval is never cleared. If the component is removed, the timer can continue running.
Correct Approach: Add Cleanup
import { useEffect } from "react";
function Timer() {
useEffect(() => {
const timerId = setInterval(() => {
console.log("Timer running");
}, 1000);
return () => {
clearInterval(timerId);
};
}, []);
return <h2>Timer Example</h2>;
}
export default Timer;
The cleanup function clears the interval when the Effect is cleaned up. This makes the Effect safe to repeat during Strict Mode checks and when the component is removed.
Effect Lifecycle in Strict Mode
Initial Mount
|
v
Effect Setup
|
v
Effect Cleanup
|
v
Effect Setup Again
|
v
Normal Component Lifecycle Continues
This additional development cycle is expected behavior. It is intended to test whether setup and cleanup work correctly rather than to indicate a React error.
9. Strict Mode and API Calls
When an Effect performs a network request, Strict Mode may cause the request to be initiated more than once during development if the Effect runs in the extra setup cycle. The first request may not be physically cancelled, even when its result is ignored.
Example: Handling a Fetch Effect
import { useEffect, useState } from "react";
function Users() {
const [users, setUsers] = useState([]);
const [error, setError] = useState("");
useEffect(() => {
const controller = new AbortController();
async function loadUsers() {
try {
const response = await fetch(
"https://jsonplaceholder.typicode.com/users",
{ signal: controller.signal }
);
if (!response.ok) {
throw new Error("Failed to load users");
}
const data = await response.json();
setUsers(data);
} catch (err) {
if (err.name !== "AbortError") {
setError(err.message);
}
}
}
loadUsers();
return () => {
controller.abort();
};
}, []);
if (error) return <p>{error}</p>;
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
export default Users;
Explanation:
- An
AbortController is created for the request.
- The request uses the controller's signal.
- When the Effect is cleaned up, the request is aborted where supported.
- The code ignores an expected abort error but reports other errors.
Important: Aborting a client request does not guarantee that a server has not already processed it. For operations that modify server data, use appropriate API design, idempotency, and event-handler-based actions rather than relying on an Effect to run only once.
10. Strict Mode and Callback Refs
Refs can be attached to DOM elements using either an object ref or a callback ref. Strict Mode performs an additional setup and cleanup cycle for callback refs in development to help find missing cleanup logic.
Example of a Callback Ref
function InputField() {
const setInputRef = node => {
if (node) {
console.log("Input attached");
}
};
return <input ref={setInputRef} />;
}
In development Strict Mode, callback refs may be called through additional setup and cleanup operations. This is intentional.
Example: Managing a Collection of DOM Nodes
import { useRef } from "react";
function ItemList({ items }) {
const nodesRef = useRef(new Map());
return (
<ul>
{items.map(item => (
<li
key={item.id}
ref={node => {
if (node) {
nodesRef.current.set(item.id, node);
} else {
nodesRef.current.delete(item.id);
}
}}
>
{item.name}
</li>
))}
</ul>
);
}
export default ItemList;
This callback handles both attachment and detachment by adding or removing nodes from the map. This prevents stale DOM references from accumulating.
React 19 note: Callback refs can return cleanup functions. When using that feature, make sure the cleanup removes the relevant reference. The example above uses the null-node callback approach and remains a straightforward pattern for maintaining the map.
11. Strict Mode and Deprecated APIs
Strict Mode can warn developers when certain deprecated React APIs are used in the component tree. These warnings are especially useful when maintaining older applications or upgrading React.
One example is the use of legacy class lifecycle methods such as UNSAFE_componentWillMount. Such APIs may make components harder to reason about and can be unsuitable for modern rendering patterns.
Recommended Practices
- Prefer function components and Hooks for new React code where appropriate.
- Replace deprecated lifecycle methods with supported alternatives.
- Review React console warnings during development.
- Consult the official React documentation before changing legacy code.
- Upgrade third-party libraries that rely on deprecated APIs when possible.
12. Strict Mode vs Production Mode
| Feature |
Development with Strict Mode |
Production Build |
| Extra render checks |
Enabled for relevant components. |
Strict Mode's extra development checks do not run. |
| Extra Effect cycle |
Enabled under the documented conditions. |
The Strict Mode development-only cycle does not run. |
| Extra callback ref checks |
Enabled for relevant callback refs. |
The extra development-only checks do not run. |
| Visible UI |
Strict Mode adds no visible UI. |
Strict Mode adds no visible UI. |
| Purpose |
Help developers detect problems. |
Run the application for users without these extra checks. |
Strict Mode does not remove normal React rendering behavior in production. It only disables the additional development checks associated with Strict Mode.
13. Common Strict Mode Misconceptions
| Misconception |
Correct Explanation |
| Strict Mode is an error. |
It is a development tool that helps expose potential bugs. |
| Strict Mode renders the UI twice in production. |
The extra Strict Mode rendering check is development-only. |
| Every event handler runs twice. |
Strict Mode does not generally double-call event handlers just because they are inside its tree. |
| Strict Mode causes every bug. |
It often reveals existing bugs or incomplete cleanup that might otherwise remain hidden. |
| Removing Strict Mode fixes the underlying problem. |
Removing it can hide the symptom, but the underlying issue may remain. |
| Every API request must always run once. |
Effects should be designed to handle setup and cleanup correctly; use appropriate strategies for requests and mutations. |
14. Common Problems and Solutions
| Problem |
Possible Cause |
Solution |
| Component logs appear twice |
Extra render invocation in development. |
Check for impure rendering; do not assume the behavior is a production bug. |
| Two requests appear in the Network tab |
An Effect is re-run during Strict Mode checks. |
Handle cancellation, ignore stale results, or use a data-fetching solution appropriate for the app. |
| Duplicate subscriptions |
Effect cleanup is missing. |
Return a cleanup function that unsubscribes or disconnects. |
| Timer continues after leaving a page |
Timer is not cleared. |
Use clearInterval() or clearTimeout() in cleanup. |
| DOM node map contains duplicates |
Callback ref does not remove detached nodes. |
Remove the node during cleanup or when the ref receives null. |
| Deprecated API warnings |
Legacy component methods or APIs are used. |
Replace deprecated usage with supported alternatives. |
15. Best Practices for Using Strict Mode
- Enable Strict Mode for the whole application when practical, especially in new projects.
- Keep component rendering pure and avoid modifying props or external data.
- Return cleanup functions from Effects that create subscriptions, timers, or connections.
- Make callback refs handle setup and cleanup correctly.
- Do not use refs to hide state that should trigger a render.
- Do not suppress warnings without understanding their cause.
- Do not remove Strict Mode merely to hide duplicate logs or requests.
- Use React Developer Tools and browser developer tools to investigate behavior.
- Test important user interactions and asynchronous behavior.
- Remember that an Effect should synchronize with an external system, not simply run a one-time action that belongs in an event handler.
16. Practical Project: Debugging a Strict Mode Application
Project Goal: Build a small React application and use Strict Mode to identify common rendering and Effect issues.
Project Requirements
- Display a list of items.
- Add an item without mutating the original list.
- Set up a timer with proper cleanup.
- Fetch data and handle request cancellation or stale results.
- Use callback refs to track selected DOM nodes without retaining removed nodes.
- Enable Strict Mode in the application entry point.
Suggested Folder Structure
src/
main.jsx
App.jsx
ItemList.jsx
Timer.jsx
Users.jsx
Project Workflow
- Wrap the root application in
.
- Run the application in development mode.
- Inspect the console and Network tab.
- Identify repeated render logs and distinguish them from actual bugs.
- Fix mutations, missing cleanup, and stale references.
- Test mounting, updating, and removing components.
- Verify that the application behaves correctly with Strict Mode enabled.
17. Interview Questions and Answers
Q1. What is Strict Mode in React?
Strict Mode is a built-in React component that enables additional development checks to help identify potential bugs.
Q2. How do you enable Strict Mode?
Import StrictMode from React and wrap the root component or a specific component subtree with .
Q3. Does Strict Mode add any HTML element?
No. Strict Mode does not render a visible UI element.
Q4. Why does a component render twice in development?
Strict Mode intentionally invokes render logic an extra time to help detect impure code. This extra check does not occur in the production build.
Q5. Does Strict Mode execute every event handler twice?
No. Strict Mode does not generally double-call event handlers. It checks specific rendering functions, Effects, callback refs, and deprecated APIs.
Q6. Why does useEffect run an extra time?
Strict Mode tests whether an Effect can correctly clean up and set itself up again. This helps expose missing cleanup logic.
Q7. How can you fix duplicate timers?
Return a cleanup function from the Effect that clears the timer using clearInterval() or clearTimeout().
Q8. Should Strict Mode be disabled to fix duplicate API calls?
Usually not. Investigate the Effect's design, cancellation, caching, and cleanup instead of hiding the issue.
Q9. Does Strict Mode affect production performance?
The additional Strict Mode checks are development-only and do not affect the production build.
Q10. Can Strict Mode be applied to only part of an application?
Yes. Wrapping a specific component subtree enables checks for that subtree and its descendants.
Q11. What is the relationship between Strict Mode and pure functions?
Strict Mode helps reveal functions that produce unintended side effects when invoked more than once. Pure rendering logic behaves predictably with the same inputs.
Q12. What is the main benefit of Strict Mode?
It helps developers detect potential bugs earlier, improving the reliability and maintainability of React applications.
18. Practice Exercises
- Enable Strict Mode in a new React project.
- Add a render log to a component and observe development behavior.
- Fix a component that mutates an array received through props.
- Create a timer Effect and implement its cleanup correctly.
- Create an Effect that subscribes to an event and unsubscribe during cleanup.
- Fetch data and handle cancellation or stale responses correctly.
- Track a collection of DOM nodes using callback refs and remove stale references.
- Explain why repeated development logs do not necessarily indicate a production issue.
19. Quick Revision
is a built-in React development tool.
- It adds no visible UI of its own.
- It helps detect impure rendering and missing cleanup logic.
- It performs an extra render check for relevant components in development.
- It performs an additional Effect setup and cleanup cycle under the documented conditions.
- It checks callback refs for missing cleanup.
- It can warn about certain deprecated APIs.
- Its extra checks do not run in production builds.
- Do not mutate props or external state during rendering.
- Clean up timers, subscriptions, connections, and DOM references correctly.
20. Official React Documentation
21. React JS Training Resources
Explore React components, Hooks, debugging techniques, and modern frontend development through these resources:
Conclusion
Strict Mode helps React developers discover potential bugs before applications reach production. By checking rendering purity, Effect cleanup, callback refs, and deprecated API usage, it encourages predictable component behavior and cleaner code. Keeping Strict Mode enabled during development and fixing the problems it reveals helps build more reliable and maintainable React applications.