Skip to content

Commit 4583342

Browse files
authored
Merge pull request #2075 from sergei-startsev/no-unsafe-aliases
Adjust `no-unsafe` rule to handle all unsafe life-cycle methods
2 parents 35c0b4d + 8d2c7a9 commit 4583342

File tree

4 files changed

+262
-21
lines changed

4 files changed

+262
-21
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ Enable the rules that you would like to use.
119119
* [react/no-this-in-sfc](docs/rules/no-this-in-sfc.md): Prevent using `this` in stateless functional components
120120
* [react/no-unescaped-entities](docs/rules/no-unescaped-entities.md): Prevent invalid characters from appearing in markup
121121
* [react/no-unknown-property](docs/rules/no-unknown-property.md): Prevent usage of unknown DOM property (fixable)
122-
* [react/no-unsafe](docs/rules/no-unsafe.md): Prevent usage of `UNSAFE_` methods
122+
* [react/no-unsafe](docs/rules/no-unsafe.md): Prevent usage of unsafe lifecycle methods
123123
* [react/no-unused-prop-types](docs/rules/no-unused-prop-types.md): Prevent definitions of unused prop types
124124
* [react/no-unused-state](docs/rules/no-unused-state.md): Prevent definitions of unused state properties
125125
* [react/no-will-update-set-state](docs/rules/no-will-update-set-state.md): Prevent usage of `setState` in `componentWillUpdate`

docs/rules/no-unsafe.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
# Prevent usage of `UNSAFE_` methods (react/no-unsafe)
1+
# Prevent usage of unsafe lifecycle methods (react/no-unsafe)
22

33
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].
44

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

9-
The rule checks the following methods: `UNSAFE_componentWillMount`, `UNSAFE_componentWillReceiveProps`, `UNSAFE_componentWillUpdate`.
9+
The rule checks the following methods:
10+
- `componentWillMount` (and `UNSAFE_componentWillMount` alias)
11+
- `componentWillReceiveProps` (and `UNSAFE_componentWillReceiveProps` alias)
12+
- `componentWillUpdate` (and `UNSAFE_componentWillUpdate` alias)
1013

1114
## Rule Details
1215

@@ -45,3 +48,50 @@ const Foo = bar({
4548
UNSAFE_componentWillUpdate: function() {}
4649
});
4750
```
51+
52+
## Rule Options
53+
```json
54+
...
55+
"react/no-unsafe": [<enabled>, { "checkAliases": <boolean> }]
56+
...
57+
```
58+
59+
### `checkAliases` (default: `false`)
60+
61+
When `true` the rule will also check aliases of unsafe methods: `componentWillMount`, `componentWillReceiveProps`, `componentWillUpdate`.
62+
63+
The following patterns are considered warnings:
64+
65+
```jsx
66+
class Foo extends React.Component {
67+
componentWillMount() {}
68+
componentWillReceiveProps() {}
69+
componentWillUpdate() {}
70+
}
71+
```
72+
73+
```jsx
74+
const Foo = createReactClass({
75+
componentWillMount: function() {},
76+
componentWillReceiveProps: function() {},
77+
componentWillUpdate: function() {}
78+
});
79+
```
80+
81+
The following patterns are **not** considered warnings:
82+
83+
```jsx
84+
class Foo extends Bar {
85+
componentWillMount() {}
86+
componentWillReceiveProps() {}
87+
componentWillUpdate() {}
88+
}
89+
```
90+
91+
```jsx
92+
const Foo = bar({
93+
componentWillMount: function() {},
94+
componentWillReceiveProps: function() {},
95+
componentWillUpdate: function() {}
96+
});
97+
```

lib/rules/no-unsafe.js

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @fileoverview Prevent usage of UNSAFE_ methods
2+
* @fileoverview Prevent usage of unsafe lifecycle methods
33
* @author Sergei Startsev
44
*/
55

@@ -17,30 +17,63 @@ const versionUtil = require('../util/version');
1717
module.exports = {
1818
meta: {
1919
docs: {
20-
description: 'Prevent usage of UNSAFE_ methods',
20+
description: 'Prevent usage of unsafe lifecycle methods',
2121
category: 'Best Practices',
2222
recommended: false,
2323
url: docsUrl('no-unsafe')
2424
},
25-
schema: []
25+
schema: [
26+
{
27+
type: 'object',
28+
properties: {
29+
checkAliases: {
30+
default: false,
31+
type: 'boolean'
32+
}
33+
},
34+
additionalProperties: false
35+
}
36+
]
2637
},
2738

2839
create: Components.detect((context, components, utils) => {
40+
const config = context.options[0] || {};
41+
const checkAliases = config.checkAliases || false;
42+
2943
const isApplicable = versionUtil.testReactVersion(context, '16.3.0');
3044
if (!isApplicable) {
3145
return {};
3246
}
3347

48+
const unsafe = {
49+
UNSAFE_componentWillMount: {
50+
newMethod: 'componentDidMount',
51+
details:
52+
'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.'
53+
},
54+
UNSAFE_componentWillReceiveProps: {
55+
newMethod: 'getDerivedStateFromProps',
56+
details:
57+
'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.'
58+
},
59+
UNSAFE_componentWillUpdate: {
60+
newMethod: 'componentDidUpdate',
61+
details:
62+
'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.'
63+
}
64+
};
65+
if (checkAliases) {
66+
unsafe.componentWillMount = unsafe.UNSAFE_componentWillMount;
67+
unsafe.componentWillReceiveProps = unsafe.UNSAFE_componentWillReceiveProps;
68+
unsafe.componentWillUpdate = unsafe.UNSAFE_componentWillUpdate;
69+
}
70+
3471
/**
3572
* Returns a list of unsafe methods
3673
* @returns {Array} A list of unsafe methods
3774
*/
3875
function getUnsafeMethods() {
39-
return [
40-
'UNSAFE_componentWillMount',
41-
'UNSAFE_componentWillReceiveProps',
42-
'UNSAFE_componentWillUpdate'
43-
];
76+
return Object.keys(unsafe);
4477
}
4578

4679
/**
@@ -63,9 +96,13 @@ module.exports = {
6396
return;
6497
}
6598

99+
const meta = unsafe[method];
100+
const newMethod = meta.newMethod;
101+
const details = meta.details;
102+
66103
context.report({
67104
node: node,
68-
message: `${method} is unsafe for use in async rendering, see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html`
105+
message: `${method} is unsafe for use in async rendering. Update the component to use ${newMethod} instead. ${details}`
69106
});
70107
}
71108

0 commit comments

Comments
 (0)