Skip to content

Commit f2856da

Browse files
authored
Merge pull request #234 from wakeless/wakeless/no-single-element-style-arrays
Add rule to stop single element style arrays
2 parents c53891b + dad2b84 commit f2856da

File tree

5 files changed

+143
-0
lines changed

5 files changed

+143
-0
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ Finally, enable all of the rules that you would like to use.
8282
"react-native/no-inline-styles": 2,
8383
"react-native/no-color-literals": 2,
8484
"react-native/no-raw-text": 2,
85+
"react-native/no-single-element-style-arrays": 2,
8586
}
8687
}
8788
```
@@ -94,6 +95,7 @@ Finally, enable all of the rules that you would like to use.
9495
* [no-inline-styles](docs/rules/no-inline-styles.md): Detect JSX components with inline styles that contain literal values
9596
* [no-color-literals](docs/rules/no-color-literals.md): Detect `StyleSheet` rules and inline styles containing color literals instead of variables
9697
* [no-raw-text](docs/rules/no-raw-text.md): Detect raw text outside of `Text` component
98+
* [no-single-element-style-arrays](docs/rules/no-raw-text.md): No style arrays that have 1 element only `<View style={[{height: 10}]}/>`
9799

98100
[npm-url]: https://npmjs.org/package/eslint-plugin-react-native
99101
[npm-image]: http://img.shields.io/npm/v/eslint-plugin-react-native.svg?style=flat-square
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# No Single Element Style Arrays are allowed
2+
3+
These cause unnecessary re-renders as each time the array's identity changes.
4+
5+
## Rule Details
6+
7+
The following pattern is not allowed:
8+
9+
```js
10+
<View style={[{height: 10}]} />
11+
```
12+

index.js

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const allRules = {
99
'sort-styles': require('./lib/rules/sort-styles'),
1010
'split-platform-components': require('./lib/rules/split-platform-components'),
1111
'no-raw-text': require('./lib/rules/no-raw-text'),
12+
'no-single-element-style-arrays': require('./lib/rules/no-single-element-style-arrays'),
1213
};
1314

1415
function configureAsError(rules) {
@@ -34,6 +35,7 @@ module.exports = {
3435
'sort-styles': 0,
3536
'split-platform-components': 0,
3637
'no-raw-text': 0,
38+
'no-single-element-style-arrays': 0
3739
},
3840
environments: {
3941
'react-native': {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @fileoverview Enforce no single element style arrays
3+
* @author Michael Gall
4+
*/
5+
6+
'use strict';
7+
8+
module.exports = {
9+
meta: {
10+
docs: {
11+
description:
12+
'Disallow single element style arrays. These cause unnecessary re-renders as the identity of the array always changes',
13+
category: 'Stylistic Issues',
14+
recommended: false,
15+
url: '',
16+
},
17+
fixable: 'code',
18+
},
19+
20+
create(context) {
21+
function reportNode(JSXExpressionNode) {
22+
context.report({
23+
node: JSXExpressionNode,
24+
message:
25+
'Single element style arrays are not necessary and cause unnecessary re-renders',
26+
fix(fixer) {
27+
const realStyleNode = JSXExpressionNode.value.expression.elements[0];
28+
const styleSource = context.getSourceCode().getText(realStyleNode);
29+
return fixer.replaceText(JSXExpressionNode.value.expression, styleSource);
30+
},
31+
});
32+
}
33+
34+
// --------------------------------------------------------------------------
35+
// Public
36+
// --------------------------------------------------------------------------
37+
return {
38+
JSXAttribute(node) {
39+
if (node.name.name !== 'style') return;
40+
if (node.value.expression.type !== 'ArrayExpression') return;
41+
if (node.value.expression.elements.length === 1) {
42+
reportNode(node);
43+
}
44+
},
45+
};
46+
},
47+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* @fileoverview Enforce no single element style arrays
3+
* @author Michael Gall
4+
*/
5+
6+
'use strict';
7+
8+
/* eslint-disable quotes */ // For better readability on tests involving quotes
9+
10+
// ------------------------------------------------------------------------------
11+
// Requirements
12+
// ------------------------------------------------------------------------------
13+
14+
const RuleTester = require('eslint').RuleTester;
15+
const rule = require('../../../lib/rules/no-single-element-style-arrays');
16+
17+
require('babel-eslint');
18+
19+
const unnecessaryArrayMessage = 'Single element style arrays are not necessary and cause unnecessary re-renders';
20+
21+
// ------------------------------------------------------------------------------
22+
// Tests
23+
// ------------------------------------------------------------------------------
24+
const config = {
25+
parser: 'babel-eslint',
26+
parserOptions: {
27+
ecmaFeatures: {
28+
classes: true,
29+
jsx: true,
30+
},
31+
},
32+
settings: {
33+
'react-native/style-sheet-object-names': ['StyleSheet', 'OtherStyleSheet'],
34+
},
35+
};
36+
37+
const ruleTester = new RuleTester(config);
38+
ruleTester.run('single-element-style-array', rule, {
39+
valid: [
40+
{
41+
code: `
42+
const Hello = React.createClass({
43+
render: function() {
44+
return <App {...props}>foo</App>;
45+
}
46+
});
47+
`,
48+
},
49+
{
50+
code: '<App>foo</App>',
51+
},
52+
{
53+
code: '<App style={woop}>foo</App>',
54+
},
55+
{
56+
code: '<App style={{woop: "woop"}}>foo</App>',
57+
},
58+
{
59+
code: '<App style={[woope, wap]}>foo</App>',
60+
},
61+
{
62+
code: '<App className="asdf" style={woop}>foo</App>',
63+
},
64+
],
65+
66+
invalid: [
67+
{
68+
code: '<App style={[woop]}>foo</App>',
69+
output: '<App style={woop}>foo</App>',
70+
errors: [{ message: unnecessaryArrayMessage }],
71+
},
72+
{
73+
code: '<App style={[{woop: "woop"}]}>foo</App>',
74+
output: '<App style={{woop: "woop"}}>foo</App>',
75+
errors: [{ message: unnecessaryArrayMessage }],
76+
},
77+
78+
],
79+
});
80+

0 commit comments

Comments
 (0)