Skip to content

Commit

Permalink
Merge pull request #1750 from sergei-startsev/no-deprecated
Browse files Browse the repository at this point in the history
[New] Adjusted no-deprecated rule for React 16.3.0
  • Loading branch information
ljharb authored Apr 10, 2018
2 parents 8973758 + 7034ffc commit d68ef96
Show file tree
Hide file tree
Showing 4 changed files with 420 additions and 151 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Enable the rules that you would like to use.
* [react/no-children-prop](docs/rules/no-children-prop.md): Prevent passing children as props
* [react/no-danger](docs/rules/no-danger.md): Prevent usage of dangerous JSX properties
* [react/no-danger-with-children](docs/rules/no-danger-with-children.md): Prevent problem with children and props.dangerouslySetInnerHTML
* [react/no-deprecated](docs/rules/no-deprecated.md): Prevent usage of deprecated methods
* [react/no-deprecated](docs/rules/no-deprecated.md): Prevent usage of deprecated methods, including component lifecyle methods
* [react/no-did-mount-set-state](docs/rules/no-did-mount-set-state.md): Prevent usage of `setState` in `componentDidMount`
* [react/no-did-update-set-state](docs/rules/no-did-update-set-state.md): Prevent usage of `setState` in `componentDidUpdate`
* [react/no-direct-mutation-state](docs/rules/no-direct-mutation-state.md): Prevent direct mutation of `this.state`
Expand Down
27 changes: 27 additions & 0 deletions docs/rules/no-deprecated.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ const propTypes = {
React.DOM.div();

import React, { PropTypes } from 'react';

class Foo extends React.Component {
componentWillMount() { }
componentWillReceiveProps() { }
componentWillUpdate() { }
// ...
}

class Foo extends React.PureComponent {
componentWillMount() { }
componentWillReceiveProps() { }
componentWillUpdate() { }
// ...
}

var Foo = createReactClass({
componentWillMount: function() {},
componentWillReceiveProps: function() {},
componentWillUpdate: function() {},
// ...
})
```

The following patterns are **not** considered warnings:
Expand All @@ -38,4 +59,10 @@ ReactDOM.render(<MyComponent />, root);
ReactDOM.findDOMNode(this.refs.foo);

import { PropTypes } from 'prop-types';

class Foo {
componentWillMount() { }
componentWillReceiveProps() { }
componentWillUpdate() { }
}
```
69 changes: 58 additions & 11 deletions lib/rules/no-deprecated.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
* @fileoverview Prevent usage of deprecated methods
* @author Yannick Croissant
* @author Scott Feeney
* @author Sergei Startsev
*/
'use strict';

const has = require('has');

const Components = require('../util/Components');
const astUtil = require('../util/ast');
const docsUrl = require('../util/docsUrl');
const pragmaUtil = require('../util/pragma');
const versionUtil = require('../util/version');
const docsUrl = require('../util/docsUrl');

// ------------------------------------------------------------------------------
// Constants
Expand All @@ -20,7 +23,7 @@ const MODULES = {
'react-addons-perf': ['ReactPerf', 'Perf']
};

const DEPRECATED_MESSAGE = '{{oldMethod}} is deprecated since React {{version}}{{newMethod}}';
const DEPRECATED_MESSAGE = '{{oldMethod}} is deprecated since React {{version}}{{newMethod}}{{refs}}';

// ------------------------------------------------------------------------------
// Rule Definition
Expand All @@ -37,7 +40,7 @@ module.exports = {
schema: []
},

create: function(context) {
create: Components.detect((context, components, utils) => {
const sourceCode = context.getSourceCode();
const pragma = pragmaUtil.getFromContext(context);

Expand Down Expand Up @@ -73,6 +76,22 @@ module.exports = {
deprecated[`${pragma}.PropTypes`] = ['15.5.0', 'the npm module prop-types'];
// 15.6.0
deprecated[`${pragma}.DOM`] = ['15.6.0', 'the npm module react-dom-factories'];
// 16.3.0
deprecated.componentWillMount = [
'16.3.0',
'UNSAFE_componentWillMount',
'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount'
];
deprecated.componentWillReceiveProps = [
'16.3.0',
'UNSAFE_componentWillReceiveProps',
'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops'
];
deprecated.componentWillUpdate = [
'16.3.0',
'UNSAFE_componentWillUpdate',
'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate'
];
return deprecated;
}

Expand All @@ -91,13 +110,17 @@ module.exports = {
return;
}
const deprecated = getDeprecated();
const version = deprecated[method][0];
const newMethod = deprecated[method][1];
const refs = deprecated[method][2];
context.report({
node: node,
message: DEPRECATED_MESSAGE,
data: {
oldMethod: method,
version: deprecated[method][0],
newMethod: deprecated[method][1] ? `, use ${deprecated[method][1]} instead` : ''
version,
newMethod: newMethod ? `, use ${newMethod} instead` : '',
refs: refs ? `, see ${refs}` : ''
}
});
}
Expand All @@ -119,6 +142,27 @@ module.exports = {
return moduleName;
}

/**
* Returns life cycle methods if available
* @param {ASTNode} node The AST node being checked.
* @returns {Array} The array of methods.
*/
function getLifeCycleMethods(node) {
const properties = astUtil.getComponentProperties(node);
return properties.map(property => astUtil.getPropertyName(property));
}

/**
* Checks life cycle methods
* @param {ASTNode} node The AST node being checked.
*/
function checkLifeCycleMethods(node) {
if (utils.isES5Component(node) || utils.isES6Component(node)) {
const methods = getLifeCycleMethods(node);
methods.forEach(method => checkDeprecation(node, method));
}
}

// --------------------------------------------------------------------------
// Public
// --------------------------------------------------------------------------
Expand All @@ -145,10 +189,10 @@ module.exports = {
VariableDeclarator: function(node) {
const reactModuleName = getReactModuleName(node);
const isRequire = node.init && node.init.callee && node.init.callee.name === 'require';
const isReactRequire =
node.init && node.init.arguments &&
node.init.arguments.length && typeof MODULES[node.init.arguments[0].value] !== 'undefined'
;
const isReactRequire = node.init
&& node.init.arguments
&& node.init.arguments.length
&& typeof MODULES[node.init.arguments[0].value] !== 'undefined';
const isDestructuring = node.id && node.id.type === 'ObjectPattern';

if (
Expand All @@ -160,8 +204,11 @@ module.exports = {
node.id.properties.forEach(property => {
checkDeprecation(node, `${reactModuleName || pragma}.${property.key.name}`);
});
}
},

ClassDeclaration: checkLifeCycleMethods,
ClassExpression: checkLifeCycleMethods,
ObjectExpression: checkLifeCycleMethods
};
}
})
};
Loading

0 comments on commit d68ef96

Please sign in to comment.