From 9bea9cd6e5aca312cc5a5ed1d4bb48baa71cdd14 Mon Sep 17 00:00:00 2001 From: Tan Nguyen Date: Thu, 13 Sep 2018 13:54:38 +0700 Subject: [PATCH] [New] add `no-arrow-function-lifecycle` --- CHANGELOG.md | 6 + README.md | 53 ++ docs/rules/no-arrow-function-lifecycle.md | 41 + index.js | 1 + lib/rules/no-arrow-function-lifecycle.js | 55 ++ lib/rules/no-typos.js | 9 + lib/util/lifecycleMethods.js | 25 + .../lib/rules/no-arrow-function-lifecycle.js | 729 ++++++++++++++++++ 8 files changed, 919 insertions(+) create mode 100644 docs/rules/no-arrow-function-lifecycle.md create mode 100644 lib/rules/no-arrow-function-lifecycle.js create mode 100644 lib/util/lifecycleMethods.js create mode 100644 tests/lib/rules/no-arrow-function-lifecycle.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 963d7a0663..5942e11708 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3457,6 +3457,12 @@ If you're still not using React 15 you can keep the old behavior by setting the [`sort-prop-types`]: docs/rules/sort-prop-types.md [`state-in-constructor`]: docs/rules/state-in-constructor.md [`static-property-placement`]: docs/rules/static-property-placement.md +<<<<<<< HEAD [`style-prop-object`]: docs/rules/style-prop-object.md [`void-dom-elements-no-children`]: docs/rules/void-dom-elements-no-children.md [`wrap-multilines`]: docs/rules/jsx-wrap-multilines.md +======= +[`jsx-curly-newline`]: docs/rules/jsx-curly-newline.md +[`jsx-no-useless-fragment`]: docs/rules/jsx-no-useless-fragment.md +[`no-arrow-function-lifecycle`]: docs/rules/no-arrow-function-lifecycle.md +>>>>>>> [New] add `no-arrow-function-lifecycle` diff --git a/README.md b/README.md index 193920c819..eff61c1a55 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,7 @@ Enable the rules that you would like to use. # List of supported rules +<<<<<<< HEAD ✔: Enabled in the [`recommended`](#recommended) configuration.\ 🔧: Fixable with [`eslint --fix`](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems). @@ -175,6 +176,58 @@ Enable the rules that you would like to use. | | | [react/style-prop-object](docs/rules/style-prop-object.md) | Enforce style prop value is an object | | | | [react/void-dom-elements-no-children](docs/rules/void-dom-elements-no-children.md) | Prevent passing of children to void DOM elements (e.g. `
`). | +======= +* [react/boolean-prop-naming](docs/rules/boolean-prop-naming.md): Enforces consistent naming for boolean props +* [react/button-has-type](docs/rules/button-has-type.md): Forbid "button" element without an explicit "type" attribute +* [react/default-props-match-prop-types](docs/rules/default-props-match-prop-types.md): Prevent extraneous defaultProps on components +* [react/destructuring-assignment](docs/rules/destructuring-assignment.md): Rule enforces consistent usage of destructuring assignment in component +* [react/display-name](docs/rules/display-name.md): Prevent missing `displayName` in a React component definition +* [react/forbid-component-props](docs/rules/forbid-component-props.md): Forbid certain props on Components +* [react/forbid-dom-props](docs/rules/forbid-dom-props.md): Forbid certain props on DOM Nodes +* [react/forbid-elements](docs/rules/forbid-elements.md): Forbid certain elements +* [react/forbid-prop-types](docs/rules/forbid-prop-types.md): Forbid certain propTypes +* [react/forbid-foreign-prop-types](docs/rules/forbid-foreign-prop-types.md): Forbid foreign propTypes +* [react/no-access-state-in-setstate](docs/rules/no-access-state-in-setstate.md): Prevent using this.state inside this.setState +* [react/no-array-index-key](docs/rules/no-array-index-key.md): Prevent using Array index in `key` props +* [react/no-arrow-function-lifecycle](docs/rules/no-arrow-function-lifecycle.md): Don't use arrow function for lifecycle methods +* [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, including component lifecycle 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` +* [react/no-find-dom-node](docs/rules/no-find-dom-node.md): Prevent usage of `findDOMNode` +* [react/no-is-mounted](docs/rules/no-is-mounted.md): Prevent usage of `isMounted` +* [react/no-multi-comp](docs/rules/no-multi-comp.md): Prevent multiple component definition per file +* [react/no-redundant-should-component-update](docs/rules/no-redundant-should-component-update.md): Prevent usage of `shouldComponentUpdate` when extending React.PureComponent +* [react/no-render-return-value](docs/rules/no-render-return-value.md): Prevent usage of the return value of `React.render` +* [react/no-set-state](docs/rules/no-set-state.md): Prevent usage of `setState` +* [react/no-typos](docs/rules/no-typos.md): Prevent common casing typos +* [react/no-string-refs](docs/rules/no-string-refs.md): Prevent using string references in `ref` attribute. +* [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 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` +* [react/prefer-es6-class](docs/rules/prefer-es6-class.md): Enforce ES5 or ES6 class for React Components +* [react/prefer-read-only-props](docs/rules/prefer-read-only-props.md): Enforce that props are read-only +* [react/prefer-stateless-function](docs/rules/prefer-stateless-function.md): Enforce stateless React Components to be written as a pure function +* [react/prop-types](docs/rules/prop-types.md): Prevent missing props validation in a React component definition +* [react/react-in-jsx-scope](docs/rules/react-in-jsx-scope.md): Prevent missing `React` when using JSX +* [react/require-default-props](docs/rules/require-default-props.md): Enforce a defaultProps definition for every prop that is not a required prop +* [react/require-optimization](docs/rules/require-optimization.md): Enforce React components to have a `shouldComponentUpdate` method +* [react/require-render-return](docs/rules/require-render-return.md): Enforce ES5 or ES6 class for returning value in render function +* [react/self-closing-comp](docs/rules/self-closing-comp.md): Prevent extra closing tags for components without children (fixable) +* [react/sort-comp](docs/rules/sort-comp.md): Enforce component methods order (fixable) +* [react/sort-prop-types](docs/rules/sort-prop-types.md): Enforce propTypes declarations alphabetical sorting +* [react/state-in-constructor](docs/rules/state-in-constructor.md): Enforce the state initialization style to be either in a constructor or with a class property +* [react/static-property-placement](docs/rules/static-property-placement.md): Enforces where React component static properties should be positioned. +* [react/style-prop-object](docs/rules/style-prop-object.md): Enforce style prop value being an object +* [react/void-dom-elements-no-children](docs/rules/void-dom-elements-no-children.md): Prevent void DOM elements (e.g. ``, `
`) from receiving children +>>>>>>> [New] add `no-arrow-function-lifecycle` ## JSX-specific rules diff --git a/docs/rules/no-arrow-function-lifecycle.md b/docs/rules/no-arrow-function-lifecycle.md new file mode 100644 index 0000000000..96d6b5b891 --- /dev/null +++ b/docs/rules/no-arrow-function-lifecycle.md @@ -0,0 +1,41 @@ +# Lifecycle methods should be methods on the prototype, not class fields (react/no-arrow-function-lifecycle) + +It is not neccessary to use arrow function for lifecycle methods. This makes things harder to test, conceptually less performant (although in practice, performance will not be affected, since most engines will optimize efficiently), and can break hot reloading patterns. + +## Rule Details + +The following patterns are considered warnings: + +```jsx +class Hello extends React.Component { + render = () => { + return
; + } +} + +var AnotherHello = createReactClass({ + render: () => { + return
; + }, +}); +``` + +The following patterns are **not** considered warnings: + +```jsx +class Hello extends React.Component { + render() { + return
; + } +} + +var AnotherHello = createReactClass({ + render() { + return
; + }, +}); + +``` +## When Not To Use It + +If you don't care about performance of your application or conceptual correctness of class property placement, you can disable this rule. diff --git a/index.js b/index.js index 15fa8f0465..ec1e15a92e 100644 --- a/index.js +++ b/index.js @@ -57,6 +57,7 @@ const allRules = { 'no-access-state-in-setstate': require('./lib/rules/no-access-state-in-setstate'), 'no-adjacent-inline-elements': require('./lib/rules/no-adjacent-inline-elements'), 'no-array-index-key': require('./lib/rules/no-array-index-key'), + 'no-arrow-function-lifecycle': require('./lib/rules/no-arrow-function-lifecycle'), 'no-children-prop': require('./lib/rules/no-children-prop'), 'no-danger': require('./lib/rules/no-danger'), 'no-danger-with-children': require('./lib/rules/no-danger-with-children'), diff --git a/lib/rules/no-arrow-function-lifecycle.js b/lib/rules/no-arrow-function-lifecycle.js new file mode 100644 index 0000000000..2ca48afe87 --- /dev/null +++ b/lib/rules/no-arrow-function-lifecycle.js @@ -0,0 +1,55 @@ +/** + * @fileoverview Lifecycle methods should be methods on the prototype, not class fields + * @author Tan Nguyen + */ +'use strict'; + +const Components = require('../util/Components'); +const astUtil = require('../util/ast'); +const docsUrl = require('../util/docsUrl'); +const lifecycleMethods = require('../util/lifecycleMethods'); + +module.exports = { + meta: { + docs: { + description: 'Lifecycle methods should be methods on the prototype, not class fields', + category: 'Best Practices', + recommended: false, + url: docsUrl('no-arrow-function-lifecycle') + }, + schema: [] + }, + + create: Components.detect((context, components) => { + /** + * @param {Array} properties list of component properties + */ + function reportNoArrowFunctionLifecycle(properties) { + properties.forEach(node => { + const propertyName = astUtil.getPropertyName(node); + const nodeType = node.value && node.value.type; + const isLifecycleMethod = lifecycleMethods.indexOf(propertyName) !== -1; + + if (nodeType === 'ArrowFunctionExpression' && isLifecycleMethod) { + context.report({ + node, + message: '{{propertyName}} is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.', + data: { + propertyName + } + }); + } + }); + } + + return { + 'Program:exit': function() { + const list = components.list(); + Object.keys(list).forEach(component => { + const properties = astUtil.getComponentProperties(list[component].node); + reportNoArrowFunctionLifecycle(properties); + }); + } + }; + }) +}; diff --git a/lib/rules/no-typos.js b/lib/rules/no-typos.js index 5e531fe355..80c06a11a8 100644 --- a/lib/rules/no-typos.js +++ b/lib/rules/no-typos.js @@ -7,12 +7,14 @@ const PROP_TYPES = Object.keys(require('prop-types')); const Components = require('../util/Components'); const docsUrl = require('../util/docsUrl'); +const lifecycleMethods = require('../util/lifecycleMethods'); // ------------------------------------------------------------------------------ // Rule Definition // ------------------------------------------------------------------------------ const STATIC_CLASS_PROPERTIES = ['propTypes', 'contextTypes', 'childContextTypes', 'defaultProps']; +<<<<<<< HEAD const STATIC_LIFECYCLE_METHODS = ['getDerivedStateFromProps']; const LIFECYCLE_METHODS = [ 'getDerivedStateFromProps', @@ -30,6 +32,8 @@ const LIFECYCLE_METHODS = [ 'componentWillUnmount', 'render' ]; +======= +>>>>>>> [New] add `no-arrow-function-lifecycle` module.exports = { meta: { @@ -157,6 +161,7 @@ module.exports = { } function reportErrorIfLifecycleMethodCasingTypo(node) { +<<<<<<< HEAD const key = node.key; let nodeKeyName = key.name; if (key.type === 'Literal') { @@ -180,6 +185,10 @@ module.exports = { LIFECYCLE_METHODS.forEach((method) => { if (method.toLowerCase() === nodeKeyName.toLowerCase() && method !== nodeKeyName) { +======= + lifecycleMethods.forEach(method => { + if (method.toLowerCase() === node.key.name.toLowerCase() && method !== node.key.name) { +>>>>>>> [New] add `no-arrow-function-lifecycle` context.report({ node, messageId: 'typoLifecycleMethod', diff --git a/lib/util/lifecycleMethods.js b/lib/util/lifecycleMethods.js new file mode 100644 index 0000000000..2fed165647 --- /dev/null +++ b/lib/util/lifecycleMethods.js @@ -0,0 +1,25 @@ +/** + * @fileoverview lifecycle methods + * @author Tan Nguyen + */ +'use strict'; + +module.exports = [ + 'getDefaultProps', + 'getInitialState', + 'getChildContext', + 'getDerivedStateFromProps', + 'componentWillMount', + 'UNSAFE_componentWillMount', + 'componentDidMount', + 'componentWillReceiveProps', + 'UNSAFE_componentWillReceiveProps', + 'shouldComponentUpdate', + 'componentWillUpdate', + 'UNSAFE_componentWillUpdate', + 'getSnapshotBeforeUpdate', + 'componentDidUpdate', + 'componentDidCatch', + 'componentWillUnmount', + 'render' +]; diff --git a/tests/lib/rules/no-arrow-function-lifecycle.js b/tests/lib/rules/no-arrow-function-lifecycle.js new file mode 100644 index 0000000000..3ef25f385c --- /dev/null +++ b/tests/lib/rules/no-arrow-function-lifecycle.js @@ -0,0 +1,729 @@ +/** + * @fileoverview It is not necessary to use arrow function for lifecycle methods + * @author Tan Nguyen + */ +'use strict'; + +const rule = require('../../../lib/rules/no-arrow-function-lifecycle'); +const RuleTester = require('eslint').RuleTester; + +require('babel-eslint'); + +const parserOptions = { + ecmaVersion: 2018, + sourceType: 'module', + ecmaFeatures: { + jsx: true + } +}; + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({parserOptions}); +ruleTester.run('no-arrow-function-lifecycle', rule, { + valid: [{ + code: ` + var Hello = createReactClass({ + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + getDefaultProps: function() { return {}; }, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + getInitialState: function() { return {}; }, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + getChildContext: function() { return {}; }, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + getDerivedStateFromProps: function() { return {}; }, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + componentWillMount: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + UNSAFE_componentWillMount: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + componentDidMount: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + componentWillReceiveProps: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + UNSAFE_componentWillReceiveProps: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + shouldComponentUpdate: function() { return true; }, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + componentWillUpdate: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + UNSAFE_componentWillUpdate: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + getSnapshotBeforeUpdate: function() { return {}; }, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + componentDidUpdate: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + componentDidCatch: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + componentWillUnmount: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + var Hello = createReactClass({ + componentWillUnmount: function() {}, + render: function() { return
; } + }); + ` + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getDefaultProps() { return {}; } + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getInitialState() { return {}; } + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getChildContext() { return {}; } + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getDerivedStateFromProps() { return {}; } + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentWillMount() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + UNSAFE_componentWillMount() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentDidMount() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentWillReceiveProps() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + UNSAFE_componentWillReceiveProps() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + shouldComponentUpdate() { return true; } + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentWillUpdate() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + UNSAFE_componentWillUpdate() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getSnapshotBeforeUpdate() { return {}; } + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentDidUpdate() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentDidCatch() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentWillUnmount() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentWillUnmount() {} + render() { return
; } + } + `, + parser: 'babel-eslint' + }], + + invalid: [{ + code: ` + var Hello = createReactClass({ + render: () => { return
; } + }); + `, + errors: [{ + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + getDefaultProps: () => { return {}; }, + render: function() { return
; } + }); + `, + errors: [{ + message: 'getDefaultProps is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + getInitialState: () => { return {}; }, + render: function() { return
; } + }); + `, + errors: [{ + message: 'getInitialState is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + getChildContext: () => { return {}; }, + render: function() { return
; } + }); + `, + errors: [{ + message: 'getChildContext is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + getDerivedStateFromProps: () => { return {}; }, + render: function() { return
; } + }); + `, + errors: [{ + message: 'getDerivedStateFromProps is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + componentWillMount: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'componentWillMount is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + UNSAFE_componentWillMount: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'UNSAFE_componentWillMount is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + componentDidMount: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'componentDidMount is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + componentWillReceiveProps: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'componentWillReceiveProps is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + UNSAFE_componentWillReceiveProps: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'UNSAFE_componentWillReceiveProps is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + shouldComponentUpdate: () => { return true; }, + render: function() { return
; } + }); + `, + errors: [{ + message: 'shouldComponentUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + componentWillUpdate: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'componentWillUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + UNSAFE_componentWillUpdate: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'UNSAFE_componentWillUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + getSnapshotBeforeUpdate: () => { return {}; }, + render: function() { return
; } + }); + `, + errors: [{ + message: 'getSnapshotBeforeUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + componentDidUpdate: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'componentDidUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + componentDidCatch: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'componentDidCatch is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + componentWillUnmount: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'componentWillUnmount is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + var Hello = createReactClass({ + componentWillUnmount: () => {}, + render: function() { return
; } + }); + `, + errors: [{ + message: 'componentWillUnmount is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getDefaultProps = () => { return {}; } + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'getDefaultProps is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getInitialState = () => { return {}; } + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'getInitialState is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getChildContext = () => { return {}; } + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'getChildContext is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getDerivedStateFromProps = () => { return {}; } + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'getDerivedStateFromProps is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentWillMount = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'componentWillMount is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + UNSAFE_componentWillMount = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'UNSAFE_componentWillMount is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentDidMount = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'componentDidMount is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentWillReceiveProps = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'componentWillReceiveProps is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + UNSAFE_componentWillReceiveProps = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'UNSAFE_componentWillReceiveProps is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + shouldComponentUpdate = () => { return true; } + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'shouldComponentUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentWillUpdate = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'componentWillUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + UNSAFE_componentWillUpdate = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'UNSAFE_componentWillUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + getSnapshotBeforeUpdate = () => { return {}; } + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'getSnapshotBeforeUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentDidUpdate = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'componentDidUpdate is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentDidCatch = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'componentDidCatch is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }, { + code: ` + class Hello extends React.Component { + handleEventMethods = () => {} + componentWillUnmount = () => {} + render = () => { return
; } + } + `, + parser: 'babel-eslint', + errors: [{ + message: 'componentWillUnmount is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }, { + message: 'render is a React lifecycle method, and should not be an arrow function. Use an instance method instead.' + }] + }] +});