Skip to content

Commit

Permalink
add ignorePureComponents option to prefer-stateless-function
Browse files Browse the repository at this point in the history
  • Loading branch information
teameh committed Aug 22, 2016
1 parent 6eabed5 commit 3d75ff6
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 45 deletions.
24 changes: 23 additions & 1 deletion docs/rules/prefer-stateless-function.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,20 @@ class Foo extends React.Component {
}
```

The following pattern is not considered a warning:

## Rule Options

```js
...
"prefer-stateless-function": [<enabled>, { "ignorePureComponent": <boolean> }]
...
```

### `ignorePureComponent`

When `true` the rule will ignore Components extending from `React.PureComponent` that use `this.props` or `this.context`.

The following patterns is considered okay and does not cause warnings:

```js
class Foo extends React.PureComponent {
Expand All @@ -55,3 +68,12 @@ class Foo extends React.PureComponent {
}
```

The following pattern is considered a warning because it's not using props or context:

```js
class Foo extends React.PureComponent {
render() {
return <div>Bar</div>;
}
}
```
2 changes: 1 addition & 1 deletion lib/rules/no-multi-comp.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ module.exports = {
* @returns {Boolean} True if the component is ignored, false if not.
*/
function isIgnored(component) {
return ignoreStateless === true && /Function/.test(component.node.type);
return ignoreStateless && /Function/.test(component.node.type);
}

// --------------------------------------------------------------------------
Expand Down
34 changes: 14 additions & 20 deletions lib/rules/prefer-stateless-function.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
'use strict';

var Components = require('../util/Components');
var pragmaUtil = require('../util/pragma');
var versionUtil = require('../util/version');

// ------------------------------------------------------------------------------
Expand All @@ -21,13 +20,22 @@ module.exports = {
category: 'Stylistic Issues',
recommended: false
},
schema: []
schema: [{
type: 'object',
properties: {
ignorePureComponents: {
default: false,
type: 'boolean'
}
},
additionalProperties: false
}]
},

create: Components.detect(function(context, components, utils) {

var pragma = pragmaUtil.getFromContext(context);
var pureComponentRegExp = new RegExp('^(' + pragma + '\\.)?PureComponent$');
var configuration = context.options[0] || {};
var ignorePureComponents = configuration.ignorePureComponents || false;

var sourceCode = context.getSourceCode();

Expand Down Expand Up @@ -68,19 +76,6 @@ module.exports = {
}
}

/**
* Checks to see if our component extends React.PureComponent
* @param {ASTNode} node The AST node being checked.
* @returns {Boolean} True if node extends React.PureComponent, false if not.
*/
var isPureComponent = function (node) {
if (node.superClass) {
return pureComponentRegExp.test(sourceCode.getText(node.superClass));
}

return false;
};

/**
* Checks whether a given array of statements is a single call of `super`.
* @see ESLint no-useless-constructor rule
Expand Down Expand Up @@ -282,10 +277,9 @@ module.exports = {

return {
ClassDeclaration: function (node) {
if (!isPureComponent(node)) {
return;
if (ignorePureComponents && utils.isPureComponent(node)) {
markSCUAsDeclared(node);
}
markSCUAsDeclared(node);
},

// Mark `this` destructuring as a usage of `this`
Expand Down
22 changes: 2 additions & 20 deletions lib/rules/require-optimization.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
'use strict';

var Components = require('../util/Components');
var pragmaUtil = require('../util/pragma');

module.exports = {
meta: {
Expand All @@ -29,15 +28,11 @@ module.exports = {
}]
},

create: Components.detect(function (context, components) {
create: Components.detect(function (context, components, utils) {
var MISSING_MESSAGE = 'Component is not optimized. Please add a shouldComponentUpdate method.';
var configuration = context.options[0] || {};
var allowDecorators = configuration.allowDecorators || [];

var pragma = pragmaUtil.getFromContext(context);
var pureComponentRegExp = new RegExp('^(' + pragma + '\\.)?PureComponent$');
var sourceCode = context.getSourceCode();

/**
* Checks to see if our component is decorated by PureRenderMixin via reactMixin
* @param {ASTNode} node The AST node being checked.
Expand Down Expand Up @@ -89,19 +84,6 @@ module.exports = {
return false;
};

/**
* Checks to see if our component extends React.PureComponent
* @param {ASTNode} node The AST node being checked.
* @returns {Boolean} True if node extends React.PureComponent, false if not.
*/
var isPureComponent = function (node) {
if (node.superClass) {
return pureComponentRegExp.test(sourceCode.getText(node.superClass));
}

return false;
};

/**
* Checks if we are declaring a shouldComponentUpdate method
* @param {ASTNode} node The AST node being checked.
Expand Down Expand Up @@ -186,7 +168,7 @@ module.exports = {
},

ClassDeclaration: function (node) {
if (!(hasPureRenderDecorator(node) || hasCustomDecorator(node) || isPureComponent(node))) {
if (!(hasPureRenderDecorator(node) || hasCustomDecorator(node) || utils.isPureComponent(node))) {
return;
}
markSCUAsDeclared(node);
Expand Down
15 changes: 14 additions & 1 deletion lib/util/Components.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,23 @@ function componentRule(rule, context) {
return relevantTags.length > 0;
},

/**
* Checks to see if our component extends React.PureComponent
*
* @param {ASTNode} node The AST node being checked.
* @returns {Boolean} True if node extends React.PureComponent, false if not
*/
isPureComponent: function (node) {
if (node.superClass) {
return new RegExp('^(' + pragma + '\\.)?PureComponent$').test(sourceCode.getText(node.superClass));
}
return false;
},

/**
* Check if the node is returning JSX
*
* @param {ASTNode} ASTnode The AST node being checked
* @param {ASTNode} node The AST node being checked
* @param {Boolean} strict If true, in a ternary condition the node must return JSX in both cases
* @returns {Boolean} True if the node is returning JSX, false if not
*/
Expand Down
26 changes: 24 additions & 2 deletions tests/lib/rules/prefer-stateless-function.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ ruleTester.run('prefer-stateless-function', rule, {
' }',
'}'
].join('\n'),
parserOptions: parserOptions
parserOptions: parserOptions,
options: [{
ignorePureComponents: true
}]
}, {
// Extends from PureComponent and uses context
code: [
Expand All @@ -57,7 +60,10 @@ ruleTester.run('prefer-stateless-function', rule, {
' }',
'}'
].join('\n'),
parserOptions: parserOptions
parserOptions: parserOptions,
options: [{
ignorePureComponents: true
}]
}, {
// Has a lifecyle method
code: [
Expand Down Expand Up @@ -289,6 +295,22 @@ ruleTester.run('prefer-stateless-function', rule, {
'}'
].join('\n'),
parserOptions: parserOptions,
options: [{
ignorePureComponents: true
}],
errors: [{
message: 'Component should be written as a pure function'
}]
}, {
// Extends from PureComponent but no ignorePureComponents option
code: [
'class Foo extends React.PureComponent {',
' render() {',
' return <div>{this.props.foo}</div>;',
' }',
'}'
].join('\n'),
parserOptions: parserOptions,
errors: [{
message: 'Component should be written as a pure function'
}]
Expand Down

0 comments on commit 3d75ff6

Please sign in to comment.