React setState Reads Its Own State

ID

javascript.react_setstate_previous_state

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

react, reliability, state

Description

Reports the object form of this.setState computing a key from the current value of that same key.

Only a key computed from itself is reported: an entry that reads a different slot than the one it writes cannot lose an update to batching, and an entry that does not read state at all is not considered. The reported node is the offending entry, so a literal that sets several keys names the one that is wrong.

Rationale

import React from "react";

class Counter extends React.Component {
  // Bad — two increments in one handler produce one
  bump() {
    this.setState({ count: this.state.count + 1 });
  }
}
  • setState does not apply the update where it is written: React batches the calls of one event and applies them together. this.state still holds the value from before the batch.

  • Two increments in the same handler — or two components bumping the same counter in response to one event — therefore produce one increment. Nothing fails; the number is simply lower than it should be, occasionally, under load.

Remediation

Use the updater form. React hands it the state as it stands when that particular update is applied, which is the value the computation needs.

import React from "react";

class Counter extends React.Component {
  // Good
  bump() {
    this.setState(previous => ({ count: previous.count + 1 }));
  }

  // Good — props are not batched state, so reading them directly is fine
  sync() {
    this.setState({ step: this.props.step });
  }
}

© 2026 Xygeni. All rights reserved