this.state value may not be directly used when updating the state in React component

  • REACT_MISUSED_UPDATE_IN_SET_STATE
  • Code Quality
  • Low
  • react

This rule applies when this.state value is directly used when updating the state in React component.

In React, this.state may not be the up-to-date value since this.state may be updated asynchronously. Therefore, if the next state is calculated using this.state value, it could be the wrong value.

Since React may batch multiple setState() calls at once in the order between componentWillReceiveProps() and shouldComponentUpdate() call, this.state may not be the up-to-date value in the following lifecycle methods:

  1. componentWillReceiveProps()
  2. UNSAFE_componentWillReceiveProps()
  3. Event handlers

To prevent the possibility of wrong update in the above lifecycle methods, use a callback function as the first argument of setState() instead of an object. The callback function receives previous state and props as the arguments, which represent the up-to-date state.

Noncompliant Code Example

View with compliant examples side by side
import React from 'react';

export class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = { counter: 0 };
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
        this.setState({ counter: this.state.counter + 1 }); // REACT_MISUSED_UPDATE_IN_SET_STATE alarm because 'this.state.counter' may not be the up-to-date value.
    }
    render() {
        return <div onClick={this.handleClick}>{this.state.counter}</div>;
    }
}

Compliant Code Example

View with noncompliant examples side by side
import React from 'react';

export class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = { counter: 0 };
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
        this.setState((prevState) => {
            return { counter: prevState.counter + 1 };
        });
    }
    render() {
        return <div onClick={this.handleClick}>{this.state.counter}</div>;
    }
}

Version

This rule was introduced in DeepScan 1.6.0-beta.

See

Was this documentation helpful?