close

state-in-constructor

Added in v0.9.4

Configuration

rslint.config.ts
import { defineConfig, reactPlugin } from '@rslint/core';

export default defineConfig([
  reactPlugin.configs.recommended,
  {
    rules: {
      'react/state-in-constructor': 'error',
    },
  },
]);

Rule details

Enforce a consistent place to initialize state in React class components.

The rule does not require components to declare state and does not provide automatic fixes.

Options

  • "always" (default): Initialize state in the constructor.
  • "never": Initialize state with a class field.
{ "react/state-in-constructor": ["error", "always"] }

Examples of incorrect code for the default "always" option:

class Counter extends React.Component {
  state = { count: 0 };
}

Examples of correct code for the default "always" option:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
}

With "never", the constructor assignment above is incorrect. Use the class field instead:

{ "react/state-in-constructor": ["error", "never"] }

Examples of correct code with "never":

class Counter extends React.Component {
  state = { count: 0 };
}

The "always" mode ignores static fields. Both modes apply only to recognized React class components.

Settings

The rule supports settings.react.pragma and @jsx annotations when identifying React class components.

Differences from upstream

rslint intentionally differs from eslint-plugin-react 7.37.5 in these cases:

  • Public string and static template keys, such as ['state'] and [`state`], are checked just like .state. Private #state and dynamic keys are ignored. For example, with const state = 'other', [state] initializes other and is not reported. Variable values and template substitutions are not resolved.
  • With "never", assignments must use a component constructor's this. Arrow functions retain that this; ordinary functions, nested class methods, field initializers, and static blocks have their own this and are not attributed to an outer constructor.
  • A private superclass such as React.#Component or React.#PureComponent does not identify a React component.
  • Static superclass keys such as React['Component'] and React[`PureComponent`] identify React components. Variable keys such as React[Component] are ignored: with const Component = 'Other', the superclass is React.Other.

For example, with "never", only the arrow's assignment is reported:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    const initialize = () => {
      this['state'] = {};
    };
    function helper() {
      this.state = {};
    }
  }
}

When not to use it

Disable this rule if your project allows both initialization styles.

Original documentation