Abhinav Anshul Doing interesting things on the Web.

Using strict mode in React 18: A guide to its new behaviors

5 min read 1420

Strict Mode In React 18

React has been around for quite some time. Each major release has introduced us to new techniques, tools, and ways of handling UI problems.

React released v18 in March 2022 and included a couple of architectural changes. This release mostly focused on shipping Concurrent Mode, new React hooks, and behavioral changes to React’s Strict Mode API. While strict mode has been a React feature for quite some time, v18 makes it more efficient in catching early bugs, thereby making the codebase more predictable.

In this article, you’ll learn about strict mode and why it was introduced in the first place. You’ll look at its various features, as well as how the v18 release has improved its API and provides even better compatibility with hooks.

Strict mode is trying to be future-ready with React’s suspense-based architecture, making it more resilient for introspecting UI issues. Let’s get started!

Introduction to React’s strict mode

Strict mode can be thought of as "use strict" notation. This was introduced some time ago in ECMAScript v5 and ensures a stricter version of JavaScript.

"use strict";
x = 3.1415;

The example above would throw an error since x is not defined. Notice how the addition of "use strict" to the top of the file ensures this. You might not even get this error in cases where "use strict" is not added , as JavaScript tends to perform weird behavior if not subjected to Strict Type definitions (like "use strict", TypeScript, flow, etc.)

Similarly, strict mode in React is a development-only tool that enforces stricter warnings and checks as you write React code.

You can enable StrictMode for any component by simply wrapping the component name as a children prop inside StrictMode, like this:

<StrictMode>
    <Button />
</StrictMode>
<StrictMode>
    <Navbar />
</StrictMode>

A more recommended way of doing this is to wrap the root App component with StrictMode. Note that App is generally the root component in create-react-app and Next.js.

<StrictMode>
    <App />
</StrictMode/>

This enforces dev time checks and warnings throughout your React codebase. Of course, make sure to import StrictMode like this:



import { StrictMode } from 'react'
 <StrictMode>
   .....
 </StrictMode>

or like this:

import React from 'react'
 <React.StrictMode>
  .....
 </React.StrictMode>

Now, we’ll take a deeper look into the various implications of where strict mode shines and helps catch issues earlier in development.

Warnings on the use of unsafe lifecycle methods

React’s class-based lifecycle methods have gone through a series of API changes. A lot of methods that were once widely used are now officially deprecated and being discouraged in support of more modern APIs.

React’s strict mode will now warn developers if they are using these deprecated APIs, such as componentWillMount, componentWillReceiveProps, and componentWillUpdate. These are now considered unsafe to use, so much so that React has added an UNSAFE prefix to these API names:

  • UNSAFE_componentWillMount
  • UNSAFE_componentWillReceiveProps
  • UNSAFE_componentWillUpdate

Strict mode is even smart enough to warn developers if any of the third-party packages being used contain these deprecated APIs. You can either modify those packages yourself or choose an alternative.

Recommending the createRef API over the legacy string ref

If you’ve worked with React when the class-based architecture was the de facto way of creating components, you might’ve used the string ref API as:

class Form extends Component {
  render() {
    return <input onClick={() => this.focus()} ref='input' />;
  }
  focus() {
    console.log(this.refs.input.value);
  }
}

While being readable and convenient to use, this API is now considered a legacy due to several reasons, including:

  • A wrapped component can’t figure out if its child component already has a ref. This problem can be solved using a callback ref pattern
  • The string ref API can be difficult to read and do static analysis on with a type checker

React’s strict mode warns the developers to either use a callback pattern or a more modern createRef API instead.

Warnings about deprecated findDOMNode usage

findDOMNode is a class-based API used to target an element deep down in the DOM tree from any component.

class Layout extends Component {


componentDidMount() {
  const nodeElement = ReactDOM.findDOMNode(this);
}


     render () {
     return <Navigation>{this.props.children}</Navigation>;
     }
    }

This may look fine, but it actually causes problems in React’s abstraction principle.

The parent element has to ensure that its children are reaching down and rendering the correct DOM nodes. A big disadvantage is that findDOMNode is a one-time calling API only, so if any node element gets changed due to some state update down the line, it won’t be reflected and updated with the findDOMNode API.

Considering all these shortcomings, strict mode warns you not to use this API and that it may get removed in future React releases.

Most of the time, the DOM element can now be targeted using ref. You can simply attach a ref reference to the element that you need to target.


More great articles from LogRocket:


class Form extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();    
}

// handle textInput.current logic here //
  render() {
    return (
      <input
          type="text"
          ref={this.textInput} 
   />       
    );
  }
}

Detecting unexpected side effects

React’s strict mode does some interesting things regarding popular inbuilt hooks like useState, useMemo, and useReducer. Specifically, it invokes these functions twice in development and once (as expected) in production mode.

This could create some confusion while debugging the code, but by doing this, strict mode makes sure to check for potential memory leaks. It also helps in making code more deterministic for the strict mode.

Not limited only to functional components, the same behavior of invoking functions twice can be found in class-based architecture as well, such as in constructor, render, shouldComponentUpdate, and more.

If you are using a create-react-app, strict mode comes on default for the entire application. While using these hooks or the state updater functions in class components, you would see even the console messages getting logged twice.

Before v18, React used to immediately silence the second console.log method when the functions were called twice. But, with v18, React doesn’t suppress any logs to enable more transparency for the developers. All those logs now get called twice during the double invocation of any functions, hooks, etc.

Warnings on the legacy context API

Similar to the refs API, we also have a legacy context API. strict mode warns against the use of legacy context API, as it will be removed from future releases. Instead, we have a more modern context API that uses the provider-consumer pattern.

const ThemeContext = React.createContext('dark')

// consume it here
 <ThemeContext.Provider value={data}>
     {children}
</ThemeContext.Provider>

This is now the recommended way of handling app state context using the new context API.

React v18 unmounting and remounting architecture

React v18 introduced new strict mode behavior regarding unmounting and remounting. Now, each element will be unmounted and remounted with the same state and effects as when the element was mounted for the first time.

A typical mounting and remounting cycle could look like this:

  • The element gets mounted for the first time
  • Side effects are created
  • Strict mode now mimics the destruction of effects
  • Side effects will be applied to the mounted components

This makes React code more resilient and helps preserve the state of a UI. For example, if a user is on the first tab and immediately switches back and forth between the first and second tabs, React needs to make sure a correct chunk of elements is getting mounted and destroyed while preserving the correct UI state and side effects.

Starting with v18, strict mode has this additional development-only behavior.

Conclusion

You have now covered everything in the strict mode update to React v18!

We have seen how strict mode affects development mode tooling. It has its own sets of rules and behavior that ensure strict warnings and checks on the codebase. This not only helps developers make the codebase future-ready but also in refactoring.

The official React team recommends enforcing app-wide strict mode to get the most out of it. For future React releases, it is expected that strict mode will get even more features to help developers like us have better tooling support.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Abhinav Anshul Doing interesting things on the Web.

Leave a Reply