Skip to content

Commit

Permalink
Add allow-in-func option to no-did-update-set-state (fixes #300)
Browse files Browse the repository at this point in the history
  • Loading branch information
yannickcr committed Nov 16, 2015
1 parent 48f67ad commit fca4db0
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 21 deletions.
25 changes: 18 additions & 7 deletions lib/rules/no-did-update-set-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

module.exports = function(context) {

var mode = context.options[0] || 'never';

// --------------------------------------------------------------------------
// Public
// --------------------------------------------------------------------------
Expand All @@ -18,25 +20,34 @@ module.exports = function(context) {

CallExpression: function(node) {
var callee = node.callee;
if (callee.type !== 'MemberExpression') {
return;
}
if (callee.object.type !== 'ThisExpression' || callee.property.name !== 'setState') {
if (
callee.type !== 'MemberExpression' ||
callee.object.type !== 'ThisExpression' ||
callee.property.name !== 'setState'
) {
return;
}
var ancestors = context.getAncestors(callee);
var ancestors = context.getAncestors(callee).reverse();
var depth = 0;
for (var i = 0, j = ancestors.length; i < j; i++) {
if (/Function(Expression|Declaration)$/.test(ancestors[i].type)) {
depth++;
}
if (
(ancestors[i].type !== 'Property' && ancestors[i].type !== 'MethodDefinition') ||
ancestors[i].key.name !== 'componentDidUpdate'
ancestors[i].key.name !== 'componentDidUpdate' ||
(mode === 'allow-in-func' && depth > 1)
) {
continue;
}
context.report(callee, 'Do not use setState in componentDidUpdate');
break;
}
}
};

};

module.exports.schema = [];
module.exports.schema = [{
enum: ['allow-in-func']
}];
179 changes: 165 additions & 14 deletions tests/lib/rules/no-did-update-set-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
var rule = require('../../../lib/rules/no-did-update-set-state');
var RuleTester = require('eslint').RuleTester;

require('babel-eslint');

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------
Expand All @@ -32,10 +34,7 @@ ruleTester.run('no-did-update-set-state', rule, {
}, {
code: [
'var Hello = React.createClass({',
'componentDidUpdate: function() {},',
' render: function() {',
' return <div>Hello {this.props.name}</div>;',
' }',
' componentDidUpdate: function() {}',
'});'
].join('\n'),
ecmaFeatures: {
Expand All @@ -47,30 +46,89 @@ ruleTester.run('no-did-update-set-state', rule, {
' componentDidUpdate: function() {',
' someNonMemberFunction(arg);',
' this.someHandler = this.setState;',
' },',
' render: function() {',
' return <div>Hello {this.props.name}</div>;',
' }',
'});'
].join('\n'),
ecmaFeatures: {
jsx: true
}
}, {
code: [
'var Hello = React.createClass({',
' componentDidUpdate: function() {',
' someClass.onSomeEvent(function(data) {',
' this.setState({',
' data: data',
' });',
' })',
' }',
'});'
].join('\n'),
options: ['allow-in-func'],
ecmaFeatures: {
jsx: true
}
}, {
code: [
'var Hello = React.createClass({',
' componentDidUpdate: function() {',
' function handleEvent(data) {',
' this.setState({',
' data: data',
' });',
' }',
' someClass.onSomeEvent(handleEvent)',
' }',
'});'
].join('\n'),
parser: 'babel-eslint',
options: ['allow-in-func'],
ecmaFeatures: {
jsx: true
}
}],

invalid: [{
code: [
'var Hello = React.createClass({',
' componentDidUpdate: function() {',
' this.setState({',
' name: this.props.name.toUpperCase()',
' data: data',
' });',
' }',
'});'
].join('\n'),
ecmaFeatures: {
jsx: true
},
errors: [{
message: 'Do not use setState in componentDidUpdate'
}]
}, {
code: [
'class Hello extends React.Component {',
' componentDidUpdate() {',
' this.setState({',
' data: data',
' });',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
errors: [{
message: 'Do not use setState in componentDidUpdate'
}]
}, {
code: [
'var Hello = React.createClass({',
' componentDidUpdate: function() {',
' this.setState({',
' data: data',
' });',
' },',
' render: function() {',
' return <div>Hello {this.state.name}</div>;',
' }',
'});'
].join('\n'),
options: ['allow-in-func'],
ecmaFeatures: {
jsx: true
},
Expand All @@ -82,11 +140,104 @@ ruleTester.run('no-did-update-set-state', rule, {
'class Hello extends React.Component {',
' componentDidUpdate() {',
' this.setState({',
' name: this.props.name.toUpperCase()',
' data: data',
' });',
' }',
' render() {',
' return <div>Hello {this.state.name}</div>;',
'}'
].join('\n'),
parser: 'babel-eslint',
options: ['allow-in-func'],
errors: [{
message: 'Do not use setState in componentDidUpdate'
}]
}, {
code: [
'var Hello = React.createClass({',
' componentDidUpdate: function() {',
' someClass.onSomeEvent(function(data) {',
' this.setState({',
' data: data',
' });',
' })',
' }',
'});'
].join('\n'),
ecmaFeatures: {
jsx: true
},
errors: [{
message: 'Do not use setState in componentDidUpdate'
}]
}, {
code: [
'class Hello extends React.Component {',
' componentDidUpdate() {',
' someClass.onSomeEvent(function(data) {',
' this.setState({',
' data: data',
' });',
' })',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
errors: [{
message: 'Do not use setState in componentDidUpdate'
}]
}, {
code: [
'var Hello = React.createClass({',
' componentDidUpdate: function() {',
' if (true) {',
' this.setState({',
' data: data',
' });',
' }',
' }',
'});'
].join('\n'),
ecmaFeatures: {
jsx: true
},
errors: [{
message: 'Do not use setState in componentDidUpdate'
}]
}, {
code: [
'class Hello extends React.Component {',
' componentDidUpdate() {',
' if (true) {',
' this.setState({',
' data: data',
' });',
' }',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
errors: [{
message: 'Do not use setState in componentDidUpdate'
}]
}, {
code: [
'var Hello = React.createClass({',
' componentDidUpdate: function() {',
' someClass.onSomeEvent((data) => this.setState({data: data}));',
' }',
'});'
].join('\n'),
parser: 'babel-eslint',
ecmaFeatures: {
jsx: true
},
errors: [{
message: 'Do not use setState in componentDidUpdate'
}]
}, {
code: [
'class Hello extends React.Component {',
' componentDidUpdate() {',
' someClass.onSomeEvent((data) => this.setState({data: data}));',
' }',
'}'
].join('\n'),
Expand Down

0 comments on commit fca4db0

Please sign in to comment.