== Why is this an issue?

React works in two phases: render and commit.

* The render phase determines what changes need to be made to e.g. the DOM. During this phase, React calls render and then compares the result to the previous render.
* The commit phase is when React applies any changes. (In the case of React DOM, this is when React inserts, updates, and removes DOM nodes.) React also calls lifecycles like `componentDidMount` and `componentDidUpdate` during this phase.

Render phase lifecycles include among others, the following lifecycle methods:

* `componentWillMount` (or its alias `UNSAFE_componentWillMount`)
* `componentWillReceiveProps` (or its alias `UNSAFE_componentWillReceiveProps`)
* `componentWillUpdate` (or its alias `UNSAFE_componentWillUpdate`)

These are considered unsafe and also happen to be the lifecycles that cause the most confusion within the React community and tend to encourage unsafe coding practices.

[source,javascript]
----
class Foo extends React.Component {
  UNSAFE_componentWillMount() {}         // Noncompliant
  UNSAFE_componentWillReceiveProps() {}  // Noncompliant
  UNSAFE_componentWillUpdate() {}        // Noncompliant
}
----


== How to fix it

Instead of `componentWillUpdate`, use `getSnapshotBeforeUpdate` together with `componentDidUpdate`. The `getSnapshotBeforeUpdate` lifecycle is called right before mutations are made. The return value for this lifecycle will be passed as the third parameter to `componentDidUpdate`. 

Instead of `componentWillReceiveProps`, Use `getDerivedStateFromProps` together with `componentDidUpdate`. The `getDerivedStateFromProps` lifecycle is invoked after a component is instantiated as well as before it is re-rendered. It can return an object to update state, or null to indicate that the new props do not require any state updates.

As for `componentWillMount`, React will call it immediately after the constructor. It only exists for historical reasons and should not be used. Instead, use one of the alternatives:

* To initialize state, declare `state` as a class field or set `this.state` inside the `constructor`.
* If you need to run a side effect or set up a subscription, move that logic to `componentDidMount` instead.

=== Code examples

==== Noncompliant code example

[source,javascript,diff-id=2,diff-type=noncompliant]
----
class myComponent extends React.Component {
  constructor(props) {
      super(props);
  }   

  componentWillMount() { // Noncompliant: "componentWillMount" is deprecated
      if (localStorage.getItem("token")) {
          this.setState({logged_in: true});
      }
  }
  // ...
}
----

==== Compliant solution

[source,javascript,diff-id=2,diff-type=compliant]
----
class myComponent extends React.Component {
  constructor(props) {
      super(props);
      
      if (localStorage.getItem("token")) {
          this.setState({logged_in: true});
      }
  }
  // ...
}
----



== Resources
=== Documentation

* React Documentation - https://react.dev/reference/react/Component#unsafe_componentwillmount[`UNSAFE_componentWillMount`]
* React Documentation - https://react.dev/reference/react/Component#unsafe_componentwillreceiveprops[`UNSAFE_componentWillReceiveProps`]
* React Documentation - https://react.dev/reference/react/Component#unsafe_componentwillupdate[`UNSAFE_componentWillUpdate`]
* React Documentation - https://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#migrating-from-legacy-lifecycles[Migrating from Legacy Lifecycles]
