From 5ab7a238900f21431482cedb84df15120973972f Mon Sep 17 00:00:00 2001 From: Sergei Startsev Date: Fri, 30 Mar 2018 02:07:02 +0300 Subject: [PATCH 1/3] Adjusted no-deprecated rule for React 16.3.0 Added warnings for componentWillMount, componentWillReceiveProps, componentWillUpdate --- README.md | 2 +- docs/rules/no-deprecated.md | 27 ++ lib/rules/no-deprecated.js | 39 ++- tests/lib/rules/no-deprecated.js | 445 +++++++++++++++++++++---------- 4 files changed, 372 insertions(+), 141 deletions(-) diff --git a/README.md b/README.md index c621fb75aa..c6b0889da5 100644 --- a/README.md +++ b/README.md @@ -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` diff --git a/docs/rules/no-deprecated.md b/docs/rules/no-deprecated.md index 77cf0ff7bb..63076fed6e 100644 --- a/docs/rules/no-deprecated.md +++ b/docs/rules/no-deprecated.md @@ -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: @@ -38,4 +59,10 @@ ReactDOM.render(, root); ReactDOM.findDOMNode(this.refs.foo); import { PropTypes } from 'prop-types'; + +class Foo { + componentWillMount() { } + componentWillReceiveProps() { } + componentWillUpdate() { } +} ``` diff --git a/lib/rules/no-deprecated.js b/lib/rules/no-deprecated.js index 6e8c88e265..0e332b7eb2 100644 --- a/lib/rules/no-deprecated.js +++ b/lib/rules/no-deprecated.js @@ -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 @@ -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); @@ -73,6 +76,10 @@ 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']; + deprecated.componentWillReceiveProps = ['16.3.0']; + deprecated.componentWillUpdate = ['16.3.0']; return deprecated; } @@ -119,6 +126,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 // -------------------------------------------------------------------------- @@ -160,8 +188,11 @@ module.exports = { node.id.properties.forEach(property => { checkDeprecation(node, `${reactModuleName || pragma}.${property.key.name}`); }); - } + }, + ClassDeclaration: checkLifeCycleMethods, + ClassExpression: checkLifeCycleMethods, + ObjectExpression: checkLifeCycleMethods }; - } + }) }; diff --git a/tests/lib/rules/no-deprecated.js b/tests/lib/rules/no-deprecated.js index 9ddcd6b906..8e589f219d 100644 --- a/tests/lib/rules/no-deprecated.js +++ b/tests/lib/rules/no-deprecated.js @@ -2,6 +2,7 @@ * @fileoverview Prevent usage of deprecated methods * @author Yannick Croissant * @author Scott Feeney + * @author Sergei Startsev */ 'use strict'; @@ -23,6 +24,13 @@ const parserOptions = { require('babel-eslint'); +function errorMessage(oldMethod, version, newMethod) { + if (!newMethod) { + newMethod = ''; + } + return `${oldMethod} is deprecated since React ${version}${newMethod}`; +} + // ------------------------------------------------------------------------------ // Tests // ------------------------------------------------------------------------------ @@ -39,151 +47,316 @@ ruleTester.run('no-deprecated', rule, { 'ReactDOM.findDOMNode(instance);', 'ReactDOMServer.renderToString(element);', 'ReactDOMServer.renderToStaticMarkup(element);', + { + code: ` + var Foo = createReactClass({ + render: function() {} + }) + ` + }, + // Non-React + { + code: ` + var Foo = createReactClassNonReact({ + componentWillMount: function() {}, + componentWillReceiveProps: function() {}, + componentWillUpdate: function() {} + }); + ` + }, + { + code: ` + var Foo = { + componentWillMount: function() {}, + componentWillReceiveProps: function() {}, + componentWillUpdate: function() {} + }; + ` + }, + { + code: ` + class Foo { + componentWillMount() {} + componentWillReceiveProps() {} + componentWillUpdate() {} + } + ` + }, // Deprecated in a later version {code: 'React.renderComponent()', settings: {react: {version: '0.11.0'}}}, {code: 'React.createClass()', settings: {react: {version: '15.4.0'}}}, - {code: 'PropTypes', settings: {react: {version: '15.4.0'}}} + {code: 'PropTypes', settings: {react: {version: '15.4.0'}}}, + { + code: ` + class Foo extends React.Component { + componentWillMount() {} + componentWillReceiveProps() {} + componentWillUpdate() {} + } + `, + settings: {react: {version: '16.2.0'}} + } ], - invalid: [{ - code: 'React.renderComponent()', - settings: {react: {version: '0.12.0'}}, - errors: [{ - message: 'React.renderComponent is deprecated since React 0.12.0, use React.render instead' - }] - }, { - code: 'Foo.renderComponent()', - settings: {react: {pragma: 'Foo', version: '0.12.0'}}, - errors: [{ - message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead' - }] - }, { - code: '/** @jsx Foo */ Foo.renderComponent()', - settings: {react: {version: '0.12.0'}}, - errors: [{ - message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead' - }] - }, { - code: 'this.transferPropsTo()', - errors: [{ - message: 'this.transferPropsTo is deprecated since React 0.12.0, use spread operator ({...}) instead' - }] - }, { - code: 'React.addons.TestUtils', - errors: [{ - message: 'React.addons.TestUtils is deprecated since React 15.5.0, use ReactDOM.TestUtils instead' - }] - }, { - code: 'React.addons.classSet()', - errors: [{ - message: 'React.addons.classSet is deprecated since React 0.13.0, use the npm module classnames instead' - }] - }, { - code: 'React.render(element, container);', - errors: [{ - message: 'React.render is deprecated since React 0.14.0, use ReactDOM.render instead' - }] - }, { - code: 'React.unmountComponentAtNode(container);', - errors: [{ - message: ( - 'React.unmountComponentAtNode is deprecated since React 0.14.0, ' + - 'use ReactDOM.unmountComponentAtNode instead' - ) - }] - }, { - code: 'React.findDOMNode(instance);', - errors: [{ - message: 'React.findDOMNode is deprecated since React 0.14.0, use ReactDOM.findDOMNode instead' - }] - }, { - code: 'React.renderToString(element);', - errors: [{ - message: 'React.renderToString is deprecated since React 0.14.0, use ReactDOMServer.renderToString instead' - }] - }, { - code: 'React.renderToStaticMarkup(element);', - errors: [{ - message: ( - 'React.renderToStaticMarkup is deprecated since React 0.14.0, ' + - 'use ReactDOMServer.renderToStaticMarkup instead' - ) - }] - }, { - code: 'React.createClass({});', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] - }, { - code: 'Foo.createClass({});', - settings: {react: {pragma: 'Foo'}}, - errors: [{ - message: 'Foo.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] - }, { - code: 'React.PropTypes', - errors: [{ - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] - }, { - code: 'var {createClass} = require(\'react\');', - parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] - }, { - code: 'var {createClass, PropTypes} = require(\'react\');', - parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }, { - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] - }, { - code: 'import {createClass} from \'react\';', - parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] - }, { - code: 'import {createClass, PropTypes} from \'react\';', - parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }, { - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] - }, { - code: ` + invalid: [ + { + code: 'React.renderComponent()', + settings: {react: {version: '0.12.0'}}, + errors: [{ + message: 'React.renderComponent is deprecated since React 0.12.0, use React.render instead' + }] + }, + { + code: 'Foo.renderComponent()', + settings: {react: {pragma: 'Foo', version: '0.12.0'}}, + errors: [{ + message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead' + }] + }, + { + code: '/** @jsx Foo */ Foo.renderComponent()', + settings: {react: {version: '0.12.0'}}, + errors: [{ + message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead' + }] + }, + { + code: 'this.transferPropsTo()', + errors: [{ + message: 'this.transferPropsTo is deprecated since React 0.12.0, use spread operator ({...}) instead' + }] + }, + { + code: 'React.addons.TestUtils', + errors: [{ + message: 'React.addons.TestUtils is deprecated since React 15.5.0, use ReactDOM.TestUtils instead' + }] + }, + { + code: 'React.addons.classSet()', + errors: [{ + message: 'React.addons.classSet is deprecated since React 0.13.0, use the npm module classnames instead' + }] + }, + { + code: 'React.render(element, container);', + errors: [{ + message: 'React.render is deprecated since React 0.14.0, use ReactDOM.render instead' + }] + }, + { + code: 'React.unmountComponentAtNode(container);', + errors: [{ + message: ( + 'React.unmountComponentAtNode is deprecated since React 0.14.0, ' + + 'use ReactDOM.unmountComponentAtNode instead' + ) + }] + }, + { + code: 'React.findDOMNode(instance);', + errors: [{ + message: 'React.findDOMNode is deprecated since React 0.14.0, use ReactDOM.findDOMNode instead' + }] + }, + { + code: 'React.renderToString(element);', + errors: [{ + message: 'React.renderToString is deprecated since React 0.14.0, use ReactDOMServer.renderToString instead' + }] + }, + { + code: 'React.renderToStaticMarkup(element);', + errors: [{ + message: ( + 'React.renderToStaticMarkup is deprecated since React 0.14.0, ' + + 'use ReactDOMServer.renderToStaticMarkup instead' + ) + }] + }, + { + code: 'React.createClass({});', + errors: [{ + message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' + }] + }, + { + code: 'Foo.createClass({});', + settings: {react: {pragma: 'Foo'}}, + errors: [{ + message: 'Foo.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' + }] + }, + { + code: 'React.PropTypes', + errors: [{ + message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' + }] + }, + { + code: 'var {createClass} = require(\'react\');', + parser: 'babel-eslint', + errors: [{ + message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' + }] + }, + { + code: 'var {createClass, PropTypes} = require(\'react\');', + parser: 'babel-eslint', + errors: [{ + message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' + }, { + message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' + }] + }, + { + code: 'import {createClass} from \'react\';', + parser: 'babel-eslint', + errors: [{ + message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' + }] + }, + { + code: 'import {createClass, PropTypes} from \'react\';', + parser: 'babel-eslint', + errors: [{ + message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' + }, { + message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' + }] + }, + { + code: ` import React from 'react'; const {createClass, PropTypes} = React; `, - parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }, { - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] - }, { - code: 'import {printDOM} from \'react-addons-perf\';', - parser: 'babel-eslint', - errors: [{ - message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead' - }] - }, { - code: ` + parser: 'babel-eslint', + errors: [{ + message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' + }, { + message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' + }] + }, + { + code: 'import {printDOM} from \'react-addons-perf\';', + parser: 'babel-eslint', + errors: [{ + message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead' + }] + }, + { + code: ` import ReactPerf from 'react-addons-perf'; const {printDOM} = ReactPerf; `, - parser: 'babel-eslint', - errors: [{ - message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead' - }] - }, - { - code: 'React.DOM.div', - errors: [{ - message: 'React.DOM is deprecated since React 15.6.0, use the npm module react-dom-factories instead' - }] - }] + parser: 'babel-eslint', + errors: [{ + message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead' + }] + }, + { + code: 'React.DOM.div', + errors: [{ + message: 'React.DOM is deprecated since React 15.6.0, use the npm module react-dom-factories instead' + }] + }, + { + code: ` + class Bar extends React.PureComponent { + componentWillMount() {} + componentWillReceiveProps() {} + componentWillUpdate() {} + }; + `, + settings: {react: {version: '16.3.0'}}, + errors: [ + {message: errorMessage('componentWillMount', '16.3.0')}, + {message: errorMessage('componentWillReceiveProps', '16.3.0')}, + {message: errorMessage('componentWillUpdate', '16.3.0')} + ], + parserOptions: parserOptions + }, + { + code: ` + function Foo() { + return class Bar extends React.PureComponent { + componentWillMount() {} + componentWillReceiveProps() {} + componentWillUpdate() {} + }; + } + `, + settings: {react: {version: '16.3.0'}}, + errors: [ + {message: errorMessage('componentWillMount', '16.3.0')}, + {message: errorMessage('componentWillReceiveProps', '16.3.0')}, + {message: errorMessage('componentWillUpdate', '16.3.0')} + ], + parserOptions: parserOptions + }, + { + code: ` + class Bar extends PureComponent { + componentWillMount() {} + componentWillReceiveProps() {} + componentWillUpdate() {} + }; + `, + settings: {react: {version: '16.3.0'}}, + errors: [ + {message: errorMessage('componentWillMount', '16.3.0')}, + {message: errorMessage('componentWillReceiveProps', '16.3.0')}, + {message: errorMessage('componentWillUpdate', '16.3.0')} + ], + parserOptions: parserOptions + }, + { + code: ` + class Foo extends React.Component { + componentWillMount() {} + componentWillReceiveProps() {} + componentWillUpdate() {} + } + `, + settings: {react: {version: '16.3.0'}}, + errors: [ + {message: errorMessage('componentWillMount', '16.3.0')}, + {message: errorMessage('componentWillReceiveProps', '16.3.0')}, + {message: errorMessage('componentWillUpdate', '16.3.0')} + ], + parserOptions: parserOptions + }, + { + code: ` + class Foo extends Component { + componentWillMount() {} + componentWillReceiveProps() {} + componentWillUpdate() {} + } + `, + settings: {react: {version: '16.3.0'}}, + errors: [ + {message: errorMessage('componentWillMount', '16.3.0')}, + {message: errorMessage('componentWillReceiveProps', '16.3.0')}, + {message: errorMessage('componentWillUpdate', '16.3.0')} + ], + parserOptions: parserOptions + }, + { + code: ` + var Foo = createReactClass({ + componentWillMount: function() {}, + componentWillReceiveProps: function() {}, + componentWillUpdate: function() {} + }) + `, + settings: {react: {version: '16.3.0'}}, + errors: [ + {message: errorMessage('componentWillMount', '16.3.0')}, + {message: errorMessage('componentWillReceiveProps', '16.3.0')}, + {message: errorMessage('componentWillUpdate', '16.3.0')} + ], + parserOptions: parserOptions + } + ] }); From 501edbf596abdeb9a8a96b40bec01b06e7d0e0d3 Mon Sep 17 00:00:00 2001 From: Sergei Startsev Date: Sun, 1 Apr 2018 22:31:15 +0300 Subject: [PATCH 2/3] Added `refs` field to refer to docs in`no-deprecated` rule, minor adjustments --- lib/rules/no-deprecated.js | 36 ++-- tests/lib/rules/no-deprecated.js | 282 +++++++++++++++++-------------- 2 files changed, 178 insertions(+), 140 deletions(-) diff --git a/lib/rules/no-deprecated.js b/lib/rules/no-deprecated.js index 0e332b7eb2..3997fb89a5 100644 --- a/lib/rules/no-deprecated.js +++ b/lib/rules/no-deprecated.js @@ -23,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 @@ -77,9 +77,21 @@ module.exports = { // 15.6.0 deprecated[`${pragma}.DOM`] = ['15.6.0', 'the npm module react-dom-factories']; // 16.3.0 - deprecated.componentWillMount = ['16.3.0']; - deprecated.componentWillReceiveProps = ['16.3.0']; - deprecated.componentWillUpdate = ['16.3.0']; + deprecated.componentWillMount = [ + '16.3.0', + 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ]; + deprecated.componentWillReceiveProps = [ + '16.3.0', + 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ]; + deprecated.componentWillUpdate = [ + '16.3.0', + 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ]; return deprecated; } @@ -98,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}` : '' } }); } @@ -173,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 ( diff --git a/tests/lib/rules/no-deprecated.js b/tests/lib/rules/no-deprecated.js index 8e589f219d..f52fc766b6 100644 --- a/tests/lib/rules/no-deprecated.js +++ b/tests/lib/rules/no-deprecated.js @@ -24,11 +24,10 @@ const parserOptions = { require('babel-eslint'); -function errorMessage(oldMethod, version, newMethod) { - if (!newMethod) { - newMethod = ''; - } - return `${oldMethod} is deprecated since React ${version}${newMethod}`; +function errorMessage(oldMethod, version, newMethod, refs) { + newMethod = newMethod ? `, use ${newMethod} instead` : ''; + refs = refs ? `, see ${refs}` : ''; + return `${oldMethod} is deprecated since React ${version}${newMethod}${refs}`; } // ------------------------------------------------------------------------------ @@ -101,129 +100,87 @@ ruleTester.run('no-deprecated', rule, { invalid: [ { code: 'React.renderComponent()', - settings: {react: {version: '0.12.0'}}, - errors: [{ - message: 'React.renderComponent is deprecated since React 0.12.0, use React.render instead' - }] + errors: [{message: errorMessage('React.renderComponent', '0.12.0', 'React.render')}] }, { code: 'Foo.renderComponent()', - settings: {react: {pragma: 'Foo', version: '0.12.0'}}, - errors: [{ - message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead' - }] + settings: {react: {pragma: 'Foo'}}, + errors: [{message: errorMessage('Foo.renderComponent', '0.12.0', 'Foo.render')}] }, { code: '/** @jsx Foo */ Foo.renderComponent()', - settings: {react: {version: '0.12.0'}}, - errors: [{ - message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead' - }] + errors: [{message: errorMessage('Foo.renderComponent', '0.12.0', 'Foo.render')}] }, { code: 'this.transferPropsTo()', - errors: [{ - message: 'this.transferPropsTo is deprecated since React 0.12.0, use spread operator ({...}) instead' - }] + errors: [{message: errorMessage('this.transferPropsTo', '0.12.0', 'spread operator ({...})')}] }, { code: 'React.addons.TestUtils', - errors: [{ - message: 'React.addons.TestUtils is deprecated since React 15.5.0, use ReactDOM.TestUtils instead' - }] + errors: [{message: errorMessage('React.addons.TestUtils', '15.5.0', 'ReactDOM.TestUtils')}] }, { code: 'React.addons.classSet()', - errors: [{ - message: 'React.addons.classSet is deprecated since React 0.13.0, use the npm module classnames instead' - }] + errors: [{message: errorMessage('React.addons.classSet', '0.13.0', 'the npm module classnames')}] }, { code: 'React.render(element, container);', - errors: [{ - message: 'React.render is deprecated since React 0.14.0, use ReactDOM.render instead' - }] + errors: [{message: errorMessage('React.render', '0.14.0', 'ReactDOM.render')}] }, { code: 'React.unmountComponentAtNode(container);', - errors: [{ - message: ( - 'React.unmountComponentAtNode is deprecated since React 0.14.0, ' + - 'use ReactDOM.unmountComponentAtNode instead' - ) - }] + errors: [{message: errorMessage('React.unmountComponentAtNode', '0.14.0', 'ReactDOM.unmountComponentAtNode')}] }, { code: 'React.findDOMNode(instance);', - errors: [{ - message: 'React.findDOMNode is deprecated since React 0.14.0, use ReactDOM.findDOMNode instead' - }] + errors: [{message: errorMessage('React.findDOMNode', '0.14.0', 'ReactDOM.findDOMNode')}] }, { code: 'React.renderToString(element);', - errors: [{ - message: 'React.renderToString is deprecated since React 0.14.0, use ReactDOMServer.renderToString instead' - }] + errors: [{message: errorMessage('React.renderToString', '0.14.0', 'ReactDOMServer.renderToString')}] }, { code: 'React.renderToStaticMarkup(element);', - errors: [{ - message: ( - 'React.renderToStaticMarkup is deprecated since React 0.14.0, ' + - 'use ReactDOMServer.renderToStaticMarkup instead' - ) - }] + errors: [{message: errorMessage('React.renderToStaticMarkup', '0.14.0', 'ReactDOMServer.renderToStaticMarkup')}] }, { code: 'React.createClass({});', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] + errors: [{message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}] }, { code: 'Foo.createClass({});', settings: {react: {pragma: 'Foo'}}, - errors: [{ - message: 'Foo.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] + errors: [{message: errorMessage('Foo.createClass', '15.5.0', 'the npm module create-react-class')}] }, { code: 'React.PropTypes', - errors: [{ - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] + errors: [{message: errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types')}] }, { code: 'var {createClass} = require(\'react\');', parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] + errors: [{message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}] }, { code: 'var {createClass, PropTypes} = require(\'react\');', parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }, { - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] + errors: [ + {message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}, + {message: errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types')} + ] }, { code: 'import {createClass} from \'react\';', parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] + errors: [{message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}] }, { code: 'import {createClass, PropTypes} from \'react\';', parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }, { - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] + errors: [ + {message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}, + {message: errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types')} + ] }, { code: ` @@ -231,34 +188,27 @@ ruleTester.run('no-deprecated', rule, { const {createClass, PropTypes} = React; `, parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }, { - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] + errors: [ + {message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}, + {message: errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types')} + ] }, { code: 'import {printDOM} from \'react-addons-perf\';', parser: 'babel-eslint', - errors: [{ - message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead' - }] + errors: [{message: errorMessage('ReactPerf.printDOM', '15.0.0', 'ReactPerf.printOperations')}] }, { code: ` - import ReactPerf from 'react-addons-perf'; - const {printDOM} = ReactPerf; - `, + import ReactPerf from 'react-addons-perf'; + const {printDOM} = ReactPerf; + `, parser: 'babel-eslint', - errors: [{ - message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead' - }] + errors: [{message: errorMessage('ReactPerf.printDOM', '15.0.0', 'ReactPerf.printOperations')}] }, { code: 'React.DOM.div', - errors: [{ - message: 'React.DOM is deprecated since React 15.6.0, use the npm module react-dom-factories instead' - }] + errors: [{message: errorMessage('React.DOM', '15.6.0', 'the npm module react-dom-factories')}] }, { code: ` @@ -268,13 +218,25 @@ ruleTester.run('no-deprecated', rule, { componentWillUpdate() {} }; `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` @@ -286,13 +248,25 @@ ruleTester.run('no-deprecated', rule, { }; } `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` @@ -302,13 +276,25 @@ ruleTester.run('no-deprecated', rule, { componentWillUpdate() {} }; `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` @@ -318,13 +304,25 @@ ruleTester.run('no-deprecated', rule, { componentWillUpdate() {} } `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` @@ -334,29 +332,53 @@ ruleTester.run('no-deprecated', rule, { componentWillUpdate() {} } `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` - var Foo = createReactClass({ - componentWillMount: function() {}, - componentWillReceiveProps: function() {}, - componentWillUpdate: function() {} - }) + var Foo = createReactClass({ + componentWillMount: function() {}, + componentWillReceiveProps: function() {}, + componentWillUpdate: function() {} + }) `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] } ] }); From 7034ffcb7ad47b1d4d4888f5413c25a4765ea6f3 Mon Sep 17 00:00:00 2001 From: Sergei Startsev Date: Mon, 2 Apr 2018 13:23:24 +0300 Subject: [PATCH 3/3] Changed warnings in `no-deprecated` rule, deprecated old lifecycle methods in favor of `UNSAFE_*` --- lib/rules/no-deprecated.js | 6 +++--- tests/lib/rules/no-deprecated.js | 36 ++++++++++++++++---------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/rules/no-deprecated.js b/lib/rules/no-deprecated.js index 3997fb89a5..6072290f73 100644 --- a/lib/rules/no-deprecated.js +++ b/lib/rules/no-deprecated.js @@ -79,17 +79,17 @@ module.exports = { // 16.3.0 deprecated.componentWillMount = [ '16.3.0', - 'constructor', + 'UNSAFE_componentWillMount', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' ]; deprecated.componentWillReceiveProps = [ '16.3.0', - 'getDerivedStateFromProps', + 'UNSAFE_componentWillReceiveProps', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' ]; deprecated.componentWillUpdate = [ '16.3.0', - 'getDerivedStateFromProps', + 'UNSAFE_componentWillUpdate', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' ]; return deprecated; diff --git a/tests/lib/rules/no-deprecated.js b/tests/lib/rules/no-deprecated.js index f52fc766b6..b1b5630c33 100644 --- a/tests/lib/rules/no-deprecated.js +++ b/tests/lib/rules/no-deprecated.js @@ -221,18 +221,18 @@ ruleTester.run('no-deprecated', rule, { errors: [ { message: errorMessage( - 'componentWillMount', '16.3.0', 'constructor', + 'componentWillMount', '16.3.0', 'UNSAFE_componentWillMount', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' ) }, { message: errorMessage( - 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'componentWillReceiveProps', '16.3.0', 'UNSAFE_componentWillReceiveProps', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' ) }, { - message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + message: errorMessage('componentWillUpdate', '16.3.0', 'UNSAFE_componentWillUpdate', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' ) } @@ -251,18 +251,18 @@ ruleTester.run('no-deprecated', rule, { errors: [ { message: errorMessage( - 'componentWillMount', '16.3.0', 'constructor', + 'componentWillMount', '16.3.0', 'UNSAFE_componentWillMount', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' ) }, { message: errorMessage( - 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'componentWillReceiveProps', '16.3.0', 'UNSAFE_componentWillReceiveProps', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' ) }, { - message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + message: errorMessage('componentWillUpdate', '16.3.0', 'UNSAFE_componentWillUpdate', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' ) } @@ -279,18 +279,18 @@ ruleTester.run('no-deprecated', rule, { errors: [ { message: errorMessage( - 'componentWillMount', '16.3.0', 'constructor', + 'componentWillMount', '16.3.0', 'UNSAFE_componentWillMount', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' ) }, { message: errorMessage( - 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'componentWillReceiveProps', '16.3.0', 'UNSAFE_componentWillReceiveProps', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' ) }, { - message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + message: errorMessage('componentWillUpdate', '16.3.0', 'UNSAFE_componentWillUpdate', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' ) } @@ -307,18 +307,18 @@ ruleTester.run('no-deprecated', rule, { errors: [ { message: errorMessage( - 'componentWillMount', '16.3.0', 'constructor', + 'componentWillMount', '16.3.0', 'UNSAFE_componentWillMount', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' ) }, { message: errorMessage( - 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'componentWillReceiveProps', '16.3.0', 'UNSAFE_componentWillReceiveProps', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' ) }, { - message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + message: errorMessage('componentWillUpdate', '16.3.0', 'UNSAFE_componentWillUpdate', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' ) } @@ -335,18 +335,18 @@ ruleTester.run('no-deprecated', rule, { errors: [ { message: errorMessage( - 'componentWillMount', '16.3.0', 'constructor', + 'componentWillMount', '16.3.0', 'UNSAFE_componentWillMount', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' ) }, { message: errorMessage( - 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'componentWillReceiveProps', '16.3.0', 'UNSAFE_componentWillReceiveProps', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' ) }, { - message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + message: errorMessage('componentWillUpdate', '16.3.0', 'UNSAFE_componentWillUpdate', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' ) } @@ -363,18 +363,18 @@ ruleTester.run('no-deprecated', rule, { errors: [ { message: errorMessage( - 'componentWillMount', '16.3.0', 'constructor', + 'componentWillMount', '16.3.0', 'UNSAFE_componentWillMount', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' ) }, { message: errorMessage( - 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'componentWillReceiveProps', '16.3.0', 'UNSAFE_componentWillReceiveProps', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' ) }, { - message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + message: errorMessage('componentWillUpdate', '16.3.0', 'UNSAFE_componentWillUpdate', 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' ) }