== 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]