https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects
We want to hear from you!Take our 2021 Community Survey!
Support Ukraine Help Provide Humanitarian Aid to Ukraine.
[svg]ReactDocsTutorialBlogCommunity
[ ]
v18.0.0 LanguagesGitHub
Strict Mode
StrictMode is a tool for highlighting potential problems in an
application. Like Fragment, StrictMode does not render any visible
UI. It activates additional checks and warnings for its descendants.
Note:
Strict mode checks are run in development mode only; they do not
impact the production build.
You can enable strict mode for any part of your application. For
example:
import React from 'react';
function ExampleApplication() {
return (
);
}
In the above example, strict mode checks will not be run against the
Header and Footer components. However, ComponentOne and ComponentTwo,
as well as all of their descendants, will have the checks.
StrictMode currently helps with:
* Identifying components with unsafe lifecycles
* Warning about legacy string ref API usage
* Warning about deprecated findDOMNode usage
* Detecting unexpected side effects
* Detecting legacy context API
* Detecting unsafe effects
Additional functionality will be added with future releases of React.
Identifying unsafe lifecycles
As explained in this blog post, certain legacy lifecycle methods are
unsafe for use in async React applications. However, if your
application uses third party libraries, it can be difficult to ensure
that these lifecycles aren't being used. Fortunately, strict mode can
help with this!
When strict mode is enabled, React compiles a list of all class
components using the unsafe lifecycles, and logs a warning message
with information about these components, like so:
strict mode unsafe lifecycles warning
Addressing the issues identified by strict mode now will make it
easier for you to take advantage of concurrent rendering in future
releases of React.
Warning about legacy string ref API usage
Previously, React provided two ways for managing refs: the legacy
string ref API and the callback API. Although the string ref API was
the more convenient of the two, it had several downsides and so our
official recommendation was to use the callback form instead.
React 16.3 added a third option that offers the convenience of a
string ref without any of the downsides:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef(); }
render() {
return ; }
componentDidMount() {
this.inputRef.current.focus(); }
}
Since object refs were largely added as a replacement for string
refs, strict mode now warns about usage of string refs.
Note:
Callback refs will continue to be supported in addition to the
new createRef API.
You don't need to replace callback refs in your components. They
are slightly more flexible, so they will remain as an advanced
feature.
Learn more about the new createRef API here.
Warning about deprecated findDOMNode usage
React used to support findDOMNode to search the tree for a DOM node
given a class instance. Normally you don't need this because you can
attach a ref directly to a DOM node.
findDOMNode can also be used on class components but this was
breaking abstraction levels by allowing a parent to demand that
certain children were rendered. It creates a refactoring hazard where
you can't change the implementation details of a component because a
parent might be reaching into its DOM node. findDOMNode only returns
the first child, but with the use of Fragments, it is possible for a
component to render multiple DOM nodes. findDOMNode is a one time
read API. It only gave you an answer when you asked for it. If a
child component renders a different node, there is no way to handle
this change. Therefore findDOMNode only worked if components always
return a single DOM node that never changes.
You can instead make this explicit by passing a ref to your custom
component and pass that along to the DOM using ref forwarding.
You can also add a wrapper DOM node in your component and attach a
ref directly to it.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.wrapper = React.createRef(); }
render() {
return
{this.props.children}
; }
}
Note:
In CSS, the display: contents attribute can be used if you don't
want the node to be part of the layout.
Detecting unexpected side effects
Conceptually, React does work in two phases:
* The render phase determines what changes need to be made to e.g.
the DOM. During this phase, React calls render and then compares
the result to the previous render.
* The commit phase is when React applies any changes. (In the case
of React DOM, this is when React inserts, updates, and removes
DOM nodes.) React also calls lifecycles like componentDidMount
and componentDidUpdate during this phase.
The commit phase is usually very fast, but rendering can be slow. For
this reason, the upcoming concurrent mode (which is not enabled by
default yet) breaks the rendering work into pieces, pausing and
resuming the work to avoid blocking the browser. This means that
React may invoke render phase lifecycles more than once before
committing, or it may invoke them without committing at all (because
of an error or a higher priority interruption).
Render phase lifecycles include the following class component
methods:
* constructor
* componentWillMount (or UNSAFE_componentWillMount)
* componentWillReceiveProps (or UNSAFE_componentWillReceiveProps)
* componentWillUpdate (or UNSAFE_componentWillUpdate)
* getDerivedStateFromProps
* shouldComponentUpdate
* render
* setState updater functions (the first argument)
Because the above methods might be called more than once, it's
important that they do not contain side-effects. Ignoring this rule
can lead to a variety of problems, including memory leaks and invalid
application state. Unfortunately, it can be difficult to detect these
problems as they can often be non-deterministic.
Strict mode can't automatically detect side effects for you, but it
can help you spot them by making them a little more deterministic.
This is done by intentionally double-invoking the following
functions:
* Class component constructor, render, and shouldComponentUpdate
methods
* Class component static getDerivedStateFromProps method
* Function component bodies
* State updater functions (the first argument to setState)
* Functions passed to useState, useMemo, or useReducer
Note:
This only applies to development mode. Lifecycles will not be
double-invoked in production mode.
For example, consider the following code:
class TopLevelRoute extends React.Component {
constructor(props) {
super(props);
SharedApplicationState.recordEvent('ExampleComponent');
}
}
At first glance, this code might not seem problematic. But if
SharedApplicationState.recordEvent is not idempotent, then
instantiating this component multiple times could lead to invalid
application state. This sort of subtle bug might not manifest during
development, or it might do so inconsistently and so be overlooked.
By intentionally double-invoking methods like the component
constructor, strict mode makes patterns like this easier to spot.
Note:
In React 17, React automatically modifies the console methods
like console.log() to silence the logs in the second call to
lifecycle functions. However, it may cause undesired behavior in
certain cases where a workaround can be used.
Starting from React 18, React does not suppress any logs.
However, if you have React DevTools installed, the logs from the
second call will appear slightly dimmed. React DevTools also
offers a setting (off by default) to suppress them completely.
Detecting legacy context API
The legacy context API is error-prone, and will be removed in a
future major version. It still works for all 16.x releases but will
show this warning message in strict mode:
warn legacy context in strict mode
Read the new context API documentation to help migrate to the new
version.
Ensuring reusable state
In the future, we'd like to add a feature that allows React to add
and remove sections of the UI while preserving state. For example,
when a user tabs away from a screen and back, React should be able to
immediately show the previous screen. To do this, React support
remounting trees using the same component state used before
unmounting.
This feature will give React better performance out-of-the-box, but
requires components to be resilient to effects being mounted and
destroyed multiple times. Most effects will work without any changes,
but some effects do not properly clean up subscriptions in the
destroy callback, or implicitly assume they are only mounted or
destroyed once.
To help surface these issues, React 18 introduces a new
development-only check to Strict Mode. This new check will
automatically unmount and remount every component, whenever a
component mounts for the first time, restoring the previous state on
the second mount.
To demonstrate the development behavior you'll see in Strict Mode
with this feature, consider what happens when React mounts a new
component. Without this change, when a component mounts, React
creates the effects:
* React mounts the component.
* Layout effects are created.
* Effects are created.
With Strict Mode starting in React 18, whenever a component mounts in
development, React will simulate immediately unmounting and
remounting the component:
* React mounts the component.
* Layout effects are created.
* Effect effects are created.
* React simulates effects being destroyed on a mounted component.
* Layout effects are destroyed.
* Effects are destroyed.
* React simulates effects being re-created on a mounted component.
* Layout effects are created
* Effect setup code runs
On the second mount, React will restore the state from the first
mount. This feature simulates user behavior such as a user tabbing
away from a screen and back, ensuring that code will properly handle
state restoration.
When the component unmounts, effects are destroyed as normal:
* React unmounts the component.
* Layout effects are destroyed.
* Effect effects are destroyed.
Note:
This only applies to development mode, production behavior is
unchanged.
For help supporting common issues, see:
* How to support Reusable State in Effects
Is this page useful?Edit this page
Installation
* Getting Started
* Add React to a Website
* Create a New React App
* CDN Links
* Release Channels
Main Concepts
* 1. Hello World
* 2. Introducing JSX
* 3. Rendering Elements
* 4. Components and Props
* 5. State and Lifecycle
* 6. Handling Events
* 7. Conditional Rendering
* 8. Lists and Keys
* 9. Forms
* 10. Lifting State Up
* 11. Composition vs Inheritance
* 12. Thinking In React
Advanced Guides
* Accessibility
* Code-Splitting
* Context
* Error Boundaries
* Forwarding Refs
* Fragments
* Higher-Order Components
* Integrating with Other Libraries
* JSX In Depth
* Optimizing Performance
* Portals
* Profiler
* React Without ES6
* React Without JSX
* Reconciliation
* Refs and the DOM
* Render Props
* Static Type Checking
* Strict Mode
* Typechecking With PropTypes
* Uncontrolled Components
* Web Components
API Reference
* React
+ React.Component
* ReactDOM
* ReactDOMClient
* ReactDOMServer
* DOM Elements
* SyntheticEvent
* Test Utilities
* Test Renderer
* JS Environment Requirements
* Glossary
Hooks
* 1. Introducing Hooks
* 2. Hooks at a Glance
* 3. Using the State Hook
* 4. Using the Effect Hook
* 5. Rules of Hooks
* 6. Building Your Own Hooks
* 7. Hooks API Reference
* 8. Hooks FAQ
Testing
* Testing Overview
* Testing Recipes
* Testing Environments
Contributing
* How to Contribute
* Codebase Overview
* Implementation Notes
* Design Principles
FAQ
* AJAX and APIs
* Babel, JSX, and Build Steps
* Passing Functions to Components
* Component State
* Styling and CSS
* File Structure
* Versioning Policy
* Virtual DOM and Internals
Docs
InstallationMain ConceptsAdvanced GuidesAPI ReferenceHooksTesting
ContributingFAQ
Channels
GitHubStack OverflowDiscussion ForumsReactiflux ChatDEV Community
FacebookTwitter
Community
Code of ConductCommunity Resources
More
TutorialBlogAcknowledgementsReact NativePrivacyTerms
Facebook Open Source
Copyright (c) 2022 Meta Platforms, Inc.