Increase your reaction skills with strict mode! Learn how to improve your code performance and detect potential bugs early
Over the years, ReactJS has undergone many changes, introducing new features and discontinuing old ones. At the time of writing this article, the current version of React is 18.2.0.
Some significant new features that were introduced in React from version 16 to 18 are:-
- React Fiber Architecture Rewrite : A complete rewrite of React's core algorithm is done, which improves performance and also enables new features such as asynchronous rendering and error thresholds
- Added new Context API : A new API has been added to pass data through the component tree without having to manually pass fixtures
- Introduction to Error Thresholds: A new feature is introduced that allows you to gracefully handle errors in your components
- React lifecycle changes : Several lifecycle methods have been deprecated in favor of new methods such as componentWillMount -> UNSAFE_componentWillMount
- Introduction to React hooks : A new way of writing stateful logic in functional components is introduced that makes code reuse and testing easier
- Addition of React Strict mode: A new feature called 'strict mode' has been introduced which helps identify stale patterns in your code and also provides feedback without affecting the production build
- Added Server-Side Rendering (SSR): Added a new feature that allows React to render server-side to improve performance and SEO
- Introduction of new features such as Suspense, Concurrency, Automatic Batching, etc.
“React Strict Mode” is a kind of passive debugging feature introduced in 2018 in React version 16.3 to help you write better React code.
In this article we will discuss the need for 'React Strict Mode'; how different 'React Strict Mode' is from exception handling and debugging techniques; features and benefits of using 'React Strict Mode' in your React software projects.
Introduction
'Strict Mode' in React helps developers adhere to the latest coding practices by identifying obsolete patterns and providing feedback during development.
By using 'React Strict Mode' you can detect potential problems early in the development process by performing additional checks and warnings that are not done in the production build.
'React Strict Mode' highlights the use of insecure lifecycle methods, identifies side effects, and detects errors and warnings that may go unnoticed during development.
Additionally, 'React Strict Mode' encourages the use of recommended patterns and best practices, leading to cleaner, more maintainable code.
‘React Strict Mode’ helps you write better React code by detecting some of the issues mentioned below: –
- Detecting unsafe lifecycle methods: React Strict Mode highlights the use of unsafe lifecycle methods, such as componentWillMount and componentWillUpdate , which are prone to causing bugs and are deprecated in newer versions of React.
- Identifying side effects: React Strict Mode warns about components that introduce side effects outside of rendering, such as modifying global variables or directly manipulating the DOM.
- Highlighting prop type issues: React Strict Mode helps detect potential issues with prop types, such as when a component is assigned an incorrect data type for a prop.
- Catching errors and warnings: React Strict Mode allows for additional checks that help detect errors and warnings that might otherwise go unnoticed during development.
- Encourage best practices: Using React Strict Mode encourages you to adopt best practices and follow recommended standards, leading to cleaner, more maintainable code.
Therefore, by highlighting the above issues and warnings about deprecated code practices, 'React Strict Mode' helps you identify and fix potential issues earlier in the development cycle, allowing you to write higher quality and more stable React code.
Let's see an example of how to use 'React Strict Mode'.
Example
Suppose we have a simple React component that renders a button and a counter: –
import React, { useState } from 'react'; function Counter { const (count, setCount) = useState(0); const handleClick = => { setCount(count + 1); }; return ( < div > < button onClick={handleClick}>Click me</ button > < p >Count: {count}</ p > </ div > ); } export default Counter;
To use “React Strict Mode”, we can simply group the component into a component
import React, { useState } from 'react'; function Counter { const (count, setCount) = useState(0); const handleClick = => { setCount(count + 1); }; return ( < React.StrictMode > < div > < button onClick={handleClick}>Click me</ button > < p >Count: {count}</ p > </ div > </ React.StrictMode > ); } export default Counter;
Now suppose we want to use the count state variable in a useEffect hook to perform a side effect when the component is mounted. We can modify the component as follows: –
import React, { useState, useEffect } from 'react'; function Counter { const (count, setCount) = useState(0); const handleClick = => { setCount(count + 1); }; useEffect( => { console.log(`Component mounted with count: ${count}`); }, (count)); return ( < React.StrictMode > < div > < button onClick={handleClick}>Click me</ button > < p >Count: {count}</ p > </ div > </ React.StrictMode > ); } export default Counter;
When we save and reload the component in the browser, we should see a warning in the console that says: –
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
This warning is produced because we are performing a state update during a render phase. To fix this, we can simply move the console.log statement to a separate function and call it in the useEffect hook:
import React, { useState, useEffect } from 'react'; function Counter { const (count, setCount) = useState(0); const handleClick = => { setCount(count + 1); }; const logCount = => { console.log(`Component mounted with count: ${count}`); }; useEffect( => { logCount; }, ); return ( < React.StrictMode > < div > < button onClick={handleClick}>Click me</ button > < p >Count: {count}</ p > </ div > </ React.StrictMode > ); } export default Counter;
Now, when we reload the component in the browser, the warning should disappear and the console.log statement should be executed correctly when the component is mounted.
Is React Strict mode similar to Javascript 'Use Strict'?
No, 'React Strict Mode' is not similar to Javascript's 'use strict', however, both were developed with a similar intention, which is to provide a tool to help developers improve the quality and maintainability of their code React.
Here is a comparison table between 'React Strict Mode' and 'JavaScript use strict ':-
Strict reaction mode | JavaScript use strict | |
Use | A feature provided by React | A directive added at the top of a JavaScript file |
Implementation | Added as a component around elements | Added as a directive at the top of a file or inside a function |
Focus | Detecting problems in React components | Enforcing stricter JavaScript rules |
Impact on code | Identifies obsolete patterns and provides feedback without affecting production build | Disables some features that may cause bugs or have unpredictable behavior and imposes stricter rules for variable declarations, function calls, and other syntax |
Does React Strict mode work as a debugger?
No, 'React Strict Mode' is not a debugger.
A debugger is used to step through code and identify specific problems during runtime, while 'React Strict Mode' is used during development to prevent potential problems from occurring in the first place.
I personally use 'React Strict Mode' and Debugger because they both complement each other and should be used in combination with other development tools such as Browser Tools and practices for optimal code quality, maintainability and efficiency.
Below is a comparison table comparing 'React Strict Mode' and Debugger to highlight the common differences between the two: –
Strict reaction mode | Debugger | |
Purpose | Helps identify potential issues in React code during development | Pauses code execution to inspect the state of a program during development |
Functionality | Performs additional checks and validations at runtime to improve code quality | Provides a powerful set of tools for debugging and troubleshooting code during development |
Use | Used to identify and prevent potential problems in code during development | Used to diagnose and fix problems in code during development |
Integration | Integrated into React applications through code | Integrated into developer tools in most modern browsers |
Characteristics | Additional runtime checks and warnings for potential code issues | Ability to set breakpoints, step through code, and inspect variables during runtime |
Benefits | Helps detect potential bugs and improve code quality during development | Enables developers to debug and troubleshoot code during development |
Limitations | Not a standalone tool for identifying and fixing problems in code | Can be time-consuming and may not always reveal the root cause of a problem |
Best practice | Should be used in combination with other development tools and practices to achieve optimal code quality | Should be used to troubleshoot and fix problems as they arise during development |
Recommended use | Useful for proactively identifying potential issues in React code | Useful for reactive debugging and troubleshooting during development |
Is React Strict mode an exception handling technique?
No, React Strict Mode is not an exception handling technique; however, both are used to identify and prevent potential problems in React code.
Exception handling is a technique used by software programmers to detect errors and unexpected events that may occur during program execution.
Here is a small example of exception handling in ReactJS: –
Example
import React, { useState } from 'react'; function Example { const (count, setCount) = useState(0); const handleIncrement = => { try { if (count >= 10) { throw new Error('Maximum limit reached!'); } setCount(count + 1); } catch (error) { console.error(error.message); } }; return ( < div > < p >Count: {count}</ p > < button onClick={handleIncrement}>Increment</ button > </ div > ); } export default Example;
In exception handling in the React example above, we have a simple React component that uses the useState hook to manage a counting state. The component also has a button that increments the count state when clicked. However, we added a try-catch block in the handleIncrement function to handle exceptions.
In the try block, we check if the count state is already at the maximum value of 10. If so, we throw a new error with the message 'Maximum limit reached!'. If the count is less than 10, we simply update the count state using the setCount function.
In the catch block, we catch any error generated in the try block and log the error message to the console using console.error.
This way, if an error is thrown in the try block, the catch block will handle it and log the error message to the console without crashing the application.
The same example above can also be written using React Strict mode and the Try and Catch block. Here it is below: –
import React, { useState } from 'react'; function Example { const (count, setCount) = useState(0); const handleIncrement = => { try { if (count >= 10) { throw new Error('Maximum limit reached!'); } setCount(count + 1); } catch (error) { console.error(error.message); } }; return ( < React.StrictMode > < div > < p >Count: {count}</ p > < button onClick={handleIncrement}>Increment</ button > </ div > </ React.StrictMode > ); } export default Example;
In the above example, we wrap our component inside the React.StrictMode component to enable strict mode. The try-and-catch blocks remain the same as in the previous example, but now any warnings or errors detected by strict mode will be displayed in the console.
As we already know that React Strict Mode will detect any potential issues or bugs in our code during development, so in this example it helps us identify any issues related to using the useState hook and ensure that our code is following best practices .
What are the best features of React Strict Mode?
While working on developing a new 'Asynchronous Rendering' feature to be released in React version 16, the React development team learned some lessons, such as legacy component lifecycles that encouraged insecure coding practices. These life cycles were: –
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
Thus, the React Strict Mode component, also known as
Gradually, more features like warnings about deprecated APIs, etc. were added for the benefit of the developer, helping them write future-proof code and also ensuring that the code is compatible with the latest versions of ReactJS.
Below are the 6 most attractive features of React Strict Mode: –
Detecting insecure lifecycle methods
React components have several lifecycle methods, such as componentDidMount and componentWillUnmount, that are invoked during various stages of the component's lifecycle.
Some of these lifecycle methods have been deprecated or removed from React version 16.3 onwards due to their tendency to encourage unsafe coding practices.
'React Strict Mode' helps you detect these unsafe lifecycle methods and warns you about their use in your code.
By detecting and eliminating insecure lifecycle methods, you can ensure your code is more robust and future-proof.
The most common insecure lifecycle methods that can cause performance, reliability, and maintainability in React are: –
- componentWillMount – This method is called right before a component is mounted in the DOM. It is considered insecure because it can cause problems with server-side rendering and lead to inconsistencies between server-side and client-side rendering.
- componentWillReceiveProps – This method is called when a component receives new props. It is considered unsafe because it can lead to unnecessary re-rendering of components and cause performance issues.
- componentWillUpdate – This method is called immediately before updating a component. It is considered insecure because it can cause problems with server-side rendering and lead to inconsistencies between server-side and client-side rendering.
- shouldComponentUpdate – This method is called before updating a component and determines whether or not the component should be updated. It is considered unsafe because it can cause performance issues, especially when used inappropriately.
- componentWillUnmount – This method is called right before a component is removed from the DOM. It is considered unsafe because it can cause memory leaks and other problems if not handled correctly.
Highlighting obsolete APIs
React is constantly evolving and some APIs that were previously recommended are now obsolete.
Therefore, if you use these deprecated APIs in your React code, they can lead your code to potential problems and bugs that you would never want as a careful React developer.
'React Strict Mode' helps identify and highlight these deprecated APIs in your code, encouraging you to update your code to use the latest and recommended APIs.
Identifying Potential Side Effects
In React, a side effect is any action that occurs outside the component, such as making an API request or updating the browser location.
Side effects can lead to unexpected behavior and bugs in your code.
'React Strict Mode' helps you identify possible side effects in your components and warns you about them.
The example we read in the introduction section of this article identifies a potential side effect and issues us a warning to correct it.
Notice about using the Legacy String Ref API
If you remember, in previous versions of React, you used string refs to reference DOM elements.
However, the string ref API has been deprecated in favor of the ref callback API, in React version 16, so using the string ref API may lead to unexpected behavior and bugs in your code.
'React Strict Mode' warns you about using the legacy string ref API and encourages you to update your React code to use the newer callback ref API, as shown in a code example below:-
Example
This example shows a React component using a simple ref API with the React.StrictMode component and warning us that we are using a legacy API.
import React, { useRef } from 'react'; function MyComponent { const inputRef="myInput"; const handleButtonClick = => { console.log(this.refs(inputRef).value); }; return ( <React.StrictMode> <div> <input type="text" ref={inputRef} /> <button onClick={handleButtonClick}>Log input value</button> </div> </React.StrictMode> ); }
The notice we received is: –
Warning: The ref string, "myInput", has been used in MyComponent. This pattern is a legacy practice and is not recommended in modern React applications. Instead, use the callback ref API introduced with React 16 and higher. Learn more about using refs safely here:
The component updated using the Callback Reference API is: –
import React, { useRef } from 'react'; function MyComponent { const inputRef = useRef(null); const handleButtonClick = => { console.log(inputRef.current.value); }; return ( <React.StrictMode> <div> <input type="text" ref={inputRef} /> <button onClick={handleButtonClick}>Log input value</button> </div> </React.StrictMode> ); }
Warning about using the legacy context API
'React Strict Mode' as of version 18 warns about using the Legacy Context API in your React code, prompting you to upgrade to a newer version of the Context API.
The new Context API is more powerful and easier to use, while offering better performance and scalability.
React.StrictMode detects use of the Legacy Context API by checking for certain patterns in the code, such as accessing a component's context property or passing an object as a context value.
Warning about deprecated use of findDOMNode
React.StrictMode warns about deprecated use of findDOMNode by checking for calls to this method in the code.
This is because findDOMNode can cause performance issues and is generally discouraged in modern React applications.
The alternative approach to using findDOMNode is to use the ref attribute to create a reference to a DOM element and then manipulate the DOM element using the reference.
Let’s see an example code as below: –
class MyComponent extends React.Component { constructor(props) { super(props); this.inputRef = React.createRef ; } handleButtonClick { console.log(this.inputRef.current.value); } render { return ( <React.StrictMode> <div> <input type="text" ref={this.inputRef} /> <button onClick={ => this.handleButtonClick }>Log input value</button> </div> </React.StrictMode> ); } }
In the above example, we create a reference to the input element using the ref and createRef attribute. We can then access the value of the input element using the current property of the ref object.
Using the ref attribute instead of findDOMNode is a more modern and efficient way to manipulate the DOM in React and is recommended by React.StrictMode.
Identifying issues related to the React v18 disassembly and reassembly architecture
In React v18, new strict mode behavior was introduced for unmounting and remounting.
With this new behavior, each element is disassembled and reassembled with exactly the same state and effects as when it was initially assembled.
The process of assembling and reassembling an element using the old behavior is as follows: –
- The element is initially assembled.
- Side effects are generated.
- Strict mode now emulates removing these effects.
- When the component is mounted again, the same side effects are applied.
This old disassembly and reassembly architecture can introduce some potential problems, such as unintended re-rendering of components or unexpected side effects. 'React Strict Mode' helps detect these issues by running components in a stricter development mode.
Let’s see how we can use React Strict Mode with this new disassembly and reassembly architecture: –
import React, { useState } from 'react'; function Counter { const (count, setCount) = useState(0); return ( < React.StrictMode > < div > < h1 >Count: {count}</ h1 > < button onClick={ => setCount(count + 1)}>Increment</ button > </ div > </ React.StrictMode > ); } export default Counter;
Improving the development experience and promoting best practices
'React Strict Mode' helps improve the development experience by detecting potential issues and bugs early in the development process and ensuring your code is more robust and future-proof.
Summary
As a React developer, you can use 'React Strict Mode' to detect potential problems early and write better code.
It detects insecure lifecycle methods, warns about obsolete APIs, identifies potential side effects, and promotes best practices that help you improve your development experience.
Strict mode in React is not a debugging tool, but it can prevent issues from being deployed to production by providing additional checks and warnings.
If you liked this, be sure to check out our other articles on React.
- 24+ React UI Component Libraries
- React vs Backbone.js: Which is better for your project?
- React WebSockets: Tutorial
- A Comprehensive Guide to Server-Side Rendering in React
- Svelte Vs React: which is better
Common questions
What is React Strict mode?
React Strict Mode is a React tool that helps identify potential problems in an application. It does not render any visible UI, but it does enable additional checks and warnings for its descendants. These checks are only run in development mode and do not affect the production build.
What is the use of strict mode in JavaScript?
JavaScript strict mode is a way of opting into a strict variant of JavaScript, with the aim of fixing bugs that affect JavaScript engine optimizations and disallowing syntax that is likely to be defined in future versions of ECMAScript. This increases code security by preventing common errors, such as accidental declarations of global variables, and making code more efficient by disabling features that slow down the JavaScript engine.