diff --git a/README.md b/README.md index fb395d4..1c85c65 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ Finally, enable all of the rules that you would like to use. "react-native/no-inline-styles": 2, "react-native/no-color-literals": 2, "react-native/no-raw-text": 2, + "react-native/no-single-element-style-arrays": 2, } } ``` @@ -94,6 +95,7 @@ Finally, enable all of the rules that you would like to use. * [no-inline-styles](docs/rules/no-inline-styles.md): Detect JSX components with inline styles that contain literal values * [no-color-literals](docs/rules/no-color-literals.md): Detect `StyleSheet` rules and inline styles containing color literals instead of variables * [no-raw-text](docs/rules/no-raw-text.md): Detect raw text outside of `Text` component +* [no-single-element-style-arrays](docs/rules/no-raw-text.md): No style arrays that have 1 element only `` [npm-url]: https://npmjs.org/package/eslint-plugin-react-native [npm-image]: http://img.shields.io/npm/v/eslint-plugin-react-native.svg?style=flat-square diff --git a/docs/rules/no-single-element-style-arrays.md b/docs/rules/no-single-element-style-arrays.md new file mode 100644 index 0000000..b8741f5 --- /dev/null +++ b/docs/rules/no-single-element-style-arrays.md @@ -0,0 +1,12 @@ +# No Single Element Style Arrays are allowed + +These cause unnecessary re-renders as each time the array's identity changes. + +## Rule Details + +The following pattern is not allowed: + +```js + +``` + diff --git a/index.js b/index.js index 7d28601..c293ffc 100644 --- a/index.js +++ b/index.js @@ -9,6 +9,7 @@ const allRules = { 'sort-styles': require('./lib/rules/sort-styles'), 'split-platform-components': require('./lib/rules/split-platform-components'), 'no-raw-text': require('./lib/rules/no-raw-text'), + 'no-single-element-style-arrays': require('./lib/rules/no-single-element-style-arrays'), }; function configureAsError(rules) { @@ -34,6 +35,7 @@ module.exports = { 'sort-styles': 0, 'split-platform-components': 0, 'no-raw-text': 0, + 'no-single-element-style-arrays': 0 }, environments: { 'react-native': { diff --git a/lib/rules/no-single-element-style-arrays.js b/lib/rules/no-single-element-style-arrays.js new file mode 100644 index 0000000..8acaa4c --- /dev/null +++ b/lib/rules/no-single-element-style-arrays.js @@ -0,0 +1,47 @@ +/** + * @fileoverview Enforce no single element style arrays + * @author Michael Gall + */ + +'use strict'; + +module.exports = { + meta: { + docs: { + description: + 'Disallow single element style arrays. These cause unnecessary re-renders as the identity of the array always changes', + category: 'Stylistic Issues', + recommended: false, + url: '', + }, + fixable: 'code', + }, + + create(context) { + function reportNode(JSXExpressionNode) { + context.report({ + node: JSXExpressionNode, + message: + 'Single element style arrays are not necessary and cause unnecessary re-renders', + fix(fixer) { + const realStyleNode = JSXExpressionNode.value.expression.elements[0]; + const styleSource = context.getSourceCode().getText(realStyleNode); + return fixer.replaceText(JSXExpressionNode.value.expression, styleSource); + }, + }); + } + + // -------------------------------------------------------------------------- + // Public + // -------------------------------------------------------------------------- + return { + JSXAttribute(node) { + if (node.name.name !== 'style') return; + if (node.value.expression.type !== 'ArrayExpression') return; + if (node.value.expression.elements.length === 1) { + reportNode(node); + } + }, + }; + }, +}; diff --git a/tests/lib/rules/no-single-element-style-arrays.js b/tests/lib/rules/no-single-element-style-arrays.js new file mode 100644 index 0000000..2709079 --- /dev/null +++ b/tests/lib/rules/no-single-element-style-arrays.js @@ -0,0 +1,80 @@ +/** + * @fileoverview Enforce no single element style arrays + * @author Michael Gall + */ + +'use strict'; + +/* eslint-disable quotes */ // For better readability on tests involving quotes + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const RuleTester = require('eslint').RuleTester; +const rule = require('../../../lib/rules/no-single-element-style-arrays'); + +require('babel-eslint'); + +const unnecessaryArrayMessage = 'Single element style arrays are not necessary and cause unnecessary re-renders'; + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ +const config = { + parser: 'babel-eslint', + parserOptions: { + ecmaFeatures: { + classes: true, + jsx: true, + }, + }, + settings: { + 'react-native/style-sheet-object-names': ['StyleSheet', 'OtherStyleSheet'], + }, +}; + +const ruleTester = new RuleTester(config); +ruleTester.run('single-element-style-array', rule, { + valid: [ + { + code: ` + const Hello = React.createClass({ + render: function() { + return foo; + } + }); + `, + }, + { + code: 'foo', + }, + { + code: 'foo', + }, + { + code: 'foo', + }, + { + code: 'foo', + }, + { + code: 'foo', + }, + ], + + invalid: [ + { + code: 'foo', + output: 'foo', + errors: [{ message: unnecessaryArrayMessage }], + }, + { + code: 'foo', + output: 'foo', + errors: [{ message: unnecessaryArrayMessage }], + }, + + ], +}); +