Skip to content

Commit

Permalink
Adjust no-unsafe rule to handle all unsafe life-cycle methods
Browse files Browse the repository at this point in the history
- Adjust `no-unsafe` rule to handle all unsafe life-cycle methods including their aliases.
- Add instructions on updating components to be consistent with React runtime warnings.
  • Loading branch information
sergei-startsev committed Dec 3, 2018
1 parent 376f5c2 commit bbe9436
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -117,7 +117,7 @@ Enable the rules that you would like to use.
* [react/no-this-in-sfc](docs/rules/no-this-in-sfc.md): Prevent using `this` in stateless functional components
* [react/no-unescaped-entities](docs/rules/no-unescaped-entities.md): Prevent invalid characters from appearing in markup
* [react/no-unknown-property](docs/rules/no-unknown-property.md): Prevent usage of unknown DOM property (fixable)
* [react/no-unsafe](docs/rules/no-unsafe.md): Prevent usage of `UNSAFE_` methods
* [react/no-unsafe](docs/rules/no-unsafe.md): Prevent usage of unsafe lifecycle methods
* [react/no-unused-prop-types](docs/rules/no-unused-prop-types.md): Prevent definitions of unused prop types
* [react/no-unused-state](docs/rules/no-unused-state.md): Prevent definitions of unused state properties
* [react/no-will-update-set-state](docs/rules/no-will-update-set-state.md): Prevent usage of `setState` in `componentWillUpdate`
Expand Down
31 changes: 29 additions & 2 deletions docs/rules/no-unsafe.md
@@ -1,18 +1,27 @@
# Prevent usage of `UNSAFE_` methods (react/no-unsafe)
# Prevent usage of unsafe lifecycle methods (react/no-unsafe)

Certain legacy lifecycle methods are [unsafe for use in async React applications][async_rendering] and cause warnings in [_strict mode_][strict_mode]. These also happen to be the lifecycles that cause the most [confusion within the React community][component_lifecycle_changes].

[async_rendering]: https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html
[strict_mode]: https://reactjs.org/docs/strict-mode.html#identifying-unsafe-lifecycles
[component_lifecycle_changes]: https://reactjs.org/blog/2018/03/29/react-v-16-3.html#component-lifecycle-changes

The rule checks the following methods: `UNSAFE_componentWillMount`, `UNSAFE_componentWillReceiveProps`, `UNSAFE_componentWillUpdate`.
The rule checks the following methods:
- `componentWillMount` (and `UNSAFE_componentWillMount` alias)
- `componentWillReceiveProps` (and `UNSAFE_componentWillReceiveProps` alias)
- `componentWillUpdate` (and `UNSAFE_componentWillUpdate` alias)

## Rule Details

The following patterns are considered warnings:

```jsx
class Foo extends React.Component {
componentWillMount() {}
componentWillReceiveProps() {}
componentWillUpdate() {}
}
// or
class Foo extends React.Component {
UNSAFE_componentWillMount() {}
UNSAFE_componentWillReceiveProps() {}
Expand All @@ -21,6 +30,12 @@ class Foo extends React.Component {
```

```jsx
const Foo = createReactClass({
componentWillMount: function() {},
componentWillReceiveProps: function() {},
componentWillUpdate: function() {}
});
// or
const Foo = createReactClass({
UNSAFE_componentWillMount: function() {},
UNSAFE_componentWillReceiveProps: function() {},
Expand All @@ -31,6 +46,12 @@ const Foo = createReactClass({
The following patterns are **not** considered warnings:

```jsx
class Foo extends Bar {
componentWillMount() {}
componentWillReceiveProps() {}
componentWillUpdate() {}
}
// or
class Foo extends Bar {
UNSAFE_componentWillMount() {}
UNSAFE_componentWillReceiveProps() {}
Expand All @@ -39,6 +60,12 @@ class Foo extends Bar {
```

```jsx
const Foo = bar({
componentWillMount: function() {},
componentWillReceiveProps: function() {},
componentWillUpdate: function() {}
});
// or
const Foo = bar({
UNSAFE_componentWillMount: function() {},
UNSAFE_componentWillReceiveProps: function() {},
Expand Down
33 changes: 25 additions & 8 deletions lib/rules/no-unsafe.js
@@ -1,5 +1,5 @@
/**
* @fileoverview Prevent usage of UNSAFE_ methods
* @fileoverview Prevent usage of unsafe lifecycle methods
* @author Sergei Startsev
*/

Expand All @@ -17,7 +17,7 @@ const versionUtil = require('../util/version');
module.exports = {
meta: {
docs: {
description: 'Prevent usage of UNSAFE_ methods',
description: 'Prevent usage of unsafe lifecycle methods',
category: 'Best Practices',
recommended: false,
url: docsUrl('no-unsafe')
Expand All @@ -31,16 +31,29 @@ module.exports = {
return {};
}

const unsafe = {};
unsafe.componentWillMount = unsafe.UNSAFE_componentWillMount = {
newMethod: 'componentDidMount',
details:
'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.'
};
unsafe.componentWillReceiveProps = unsafe.UNSAFE_componentWillReceiveProps = {
newMethod: 'getDerivedStateFromProps',
details:
'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.'
};
unsafe.componentWillUpdate = unsafe.UNSAFE_componentWillUpdate = {
newMethod: 'componentDidUpdate',
details:
'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.'
};

/**
* Returns a list of unsafe methods
* @returns {Array} A list of unsafe methods
*/
function getUnsafeMethods() {
return [
'UNSAFE_componentWillMount',
'UNSAFE_componentWillReceiveProps',
'UNSAFE_componentWillUpdate'
];
return Object.keys(unsafe);
}

/**
Expand All @@ -63,9 +76,13 @@ module.exports = {
return;
}

const meta = unsafe[method];
const newMethod = meta.newMethod;
const details = meta.details;

context.report({
node: node,
message: `${method} is unsafe for use in async rendering, see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html`
message: `${method} is unsafe for use in async rendering. Update the component to use ${newMethod} instead. ${details}`
});
}

Expand Down

0 comments on commit bbe9436

Please sign in to comment.