logoESLint React

no-set-state-in-component-did-mount

Disallows calling 'this.setState' in 'componentDidMount' outside functions such as callbacks.

Full Name in eslint-plugin-react-x

react-x/no-set-state-in-component-did-mount

Full Name in @eslint-react/eslint-plugin

@eslint-react/no-set-state-in-component-did-mount

Presets

x recommended recommended-typescript recommended-type-checked strict strict-typescript strict-type-checked

Rule Details

Updating the state after a component mounts will trigger a second render() call and can lead to property/layout thrashing.

For class components, prefer setting the initial state in the constructor or via a class field initializer. If you need to perform side effects, consider using useEffect after migrating to function components.

Note that the official React documentation allows calling setState immediately in componentDidMount for cases like modals and tooltips, where you need to measure a DOM node before rendering something that depends on its size or position. This rule still reports such calls, so you can disable it selectively for those cases.

Examples

Calling setState directly in componentDidMount

// 🔴 Problem: Calling setState directly in componentDidMount triggers an extra render and can cause performance issues and layout thrashing
import React from "react";

interface MyComponentProps {}

interface MyComponentState {
  name: string;
}

class MyComponent extends React.Component<MyComponentProps, MyComponentState> {
  componentDidMount() {
    this.setState({ name: "John" });
    //   ^^^ Do not call `this.setState` in `componentDidMount` outside functions such as callbacks.
  }

  render() {
    return <div>Hello {this.state.name}</div>;
  }
}

Setting initial state correctly

Set the initial state in the constructor or via a class field. Use componentDidMount only for side effects like subscriptions or data fetching, and only call setState inside callbacks (e.g., event handlers or network responses).

// 🟢 Recommended: Initialize state in the constructor or as a class field
import React from "react";

interface MyComponentProps {}

interface MyComponentState {
  name: string;
}

class MyComponent extends React.Component<MyComponentProps, MyComponentState> {
  state = {
    name: "John",
  };

  componentDidMount() {
    // Side effects like fetching data are fine here
    fetchData().then((data) => {
      this.setState({ name: data.name }); // OK inside a callback
    });
  }

  render() {
    return <div>Hello {this.state.name}</div>;
  }
}

Resources

Further Reading


See Also

On this page