Unsafe legacy lifecycle methods of a React class component should not be defined together with newly added replacements
- REACT_UNINVOKED_UNSAFE_LIFECYCLE
- Error
- Medium
- react
This rule applies when the unsafe legacy lifecycle methods of a React class component are defined together with newly added replacements.
In React v16.3, componentWillMount()
, componentWillReceiveProps()
, and componentWillUpdate()
were marked as unsafe by adding the prefix UNSAFE_
, like USAFE_componentWillMount()
.
They have often been misused and may cause more problems with the upcoming async rendering.
As safer alternatives for those methods, getSnapshotBeforeUpdate()
and getDerivedStateFromProps()
were newly added.
Since the roles of the unsafe methods and the newly added methods may overlap, React prevents the unsafe methods from being called when the alternatives are defined and outputs a warning message.
Noncompliant Code Example
View with compliant examples side by sideimport React from 'react';
export class Hello extends React.Component {
constructor(props) {
super(props);
this.state = { msg: 'hi' };
this.handleClick = this.handleClick.bind(this);
this.helloRef = React.createRef();
}
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevState.msg !== this.state.msg) {
const hello = this.helloRef.current;
return hello.offsetLeft;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
this.helloRef.current.style.left = (snapshot + 10) + "px";
}
}
UNSAFE_componentWillUpdate(nextProps, nextState) { // REACT_UNINVOKED_UNSAFE_LIFECYCLE alarm because 'getSnapshotBeforeUpdate()' is defined.
this.curOffsetLeft = this.helloRef.current.offsetLeft;
}
handleClick() {
if (this.state.msg === 'hi') {
this.setState({ msg: 'bye' });
} else {
this.setState({ msg: 'hi' });
}
}
render() {
return <div ref={this.helloRef} onClick={this.handleClick} style={{ position: "absolute" }}>{this.state.msg}</div>;
}
}
Compliant Code Example
View with noncompliant examples side by sideimport React from 'react';
export class Hello extends React.Component {
constructor(props) {
super(props);
this.state = { msg: 'hi' };
this.handleClick = this.handleClick.bind(this);
this.helloRef = React.createRef();
}
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevState.msg !== this.state.msg) {
const hello = this.helloRef.current;
return hello.offsetLeft;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
this.helloRef.current.style.left = (snapshot + 10) + "px";
}
}
handleClick() {
if (this.state.msg === 'hi') {
this.setState({ msg: 'bye' });
} else {
this.setState({ msg: 'hi' });
}
}
render() {
return <div ref={this.helloRef} onClick={this.handleClick} style={{ position: "absolute" }}>{this.state.msg}</div>;
}
}
Version
This rule was introduced in DeepScan 1.13.0-beta.
See
React Warning: Unsafe legacy lifecycles will not be called for components using new component APIs. Hello uses getSnapshotBeforeUpdate() but also contains the following legacy lifecycles: UNSAFE_componentWillUpdate. The above lifecycles should be removed. Learn more about this warning here: https://react.dev/link/unsafe-component-lifecycles