Skip to main content
interlace
Plugin: react-featuresRules

no-did-mount-set-state

no-did-mount-set-state rule

Prevent calling setState in componentDidMount. This rule is part of eslint-plugin-react-features.

Quick Summary

AspectDetails
SeverityWarning (performance)
Auto-Fix❌ No (requires refactoring)
CategoryReact
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForReact class components

Rule Details

Calling setState immediately in componentDidMount causes an additional render cycle. Initial state should be set in the constructor or derived from props.

Why This Matters

IssueImpactSolution
🔄 Double renderPerformance degradationSet state in constructor
🐛 Wasted cyclesUnnecessary DOM updatesUse derived state
🔍 FlickerUI may flash between statesInitialize state properly

Examples

❌ Incorrect

class UserProfile extends React.Component {
  state = { user: null };
  
  componentDidMount() {
    // BAD: Immediate setState causes extra render
    this.setState({ loading: true });
    
    // This is also problematic
    this.setState({
      windowWidth: window.innerWidth
    });
  }
}

✅ Correct

class UserProfile extends React.Component {
  // GOOD: initial state is set up front, not in a second render
  state = { user: null, windowWidth: window.innerWidth };

  componentDidMount() {
    // GOOD: setState in a callback runs after the data arrives
    fetchUser(this.props.id).then((user) => this.setState({ user }));
  }
}

The rule reports a component's own this.setState(…) (also this['setState']) that runs synchronously in componentDidMount — declared as a method, an arrow property or a quoted key — on a class that extends React's Component / PureComponent, however it is imported. A call inside a callback (a promise handler, a timer) runs later and is not reported; neither is another object's setState (store.setState(…)).

Configuration Examples

Basic Usage

{
  rules: {
    'react-features/no-did-mount-set-state': 'warn'
  }
}

Further Reading

Known False Negatives

  • setState reached through another method: componentDidMount() { this.load(); } where load calls this.setState synchronously is not followed.
  • An alias of this: const self = this; self.setState(...) is not read as the component's setState.
  • createReactClass components are not covered; only classes that extend React's Component / PureComponent.

Not reported by design: setState inside a callback (fetchData().then(...), a timer), which runs after mount.

Use this rule

npm install -D oxlint-plugin-react-features
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-react-features"],  "rules": {    "react-features/no-did-mount-set-state": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-react-features'],    rules: {      'react-features/no-did-mount-set-state': 'error',    },  },});

oxlint-plugin-react-features re-exports eslint-plugin-react-features/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.