Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] no-access-state-in-setstate: add check for class component #2711

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 11 additions & 2 deletions lib/rules/no-access-state-in-setstate.js
Expand Up @@ -6,6 +6,7 @@
'use strict';

const docsUrl = require('../util/docsUrl');
const Components = require('../util/Components');

// ------------------------------------------------------------------------------
// Rule Definition
Expand All @@ -21,7 +22,7 @@ module.exports = {
}
},

create(context) {
create: Components.detect((context, components, utils) => {
function isSetStateCall(node) {
return node.type === 'CallExpression'
&& node.callee.property
Expand All @@ -39,13 +40,20 @@ module.exports = {
return current.arguments[0] === node;
}

function isClassComponent() {
return !!(utils.getParentES6Component() || utils.getParentES5Component());
}

// The methods array contains all methods or functions that are using this.state
// or that are calling another method or function using this.state
const methods = [];
// The vars array contains all variables that contains this.state
const vars = [];
return {
CallExpression(node) {
if (!isClassComponent()) {
return;
}
// Appends all the methods that are calling another
// method containing this.state to the methods array
methods.forEach((method) => {
Expand Down Expand Up @@ -89,6 +97,7 @@ module.exports = {
if (
node.property.name === 'state'
&& node.object.type === 'ThisExpression'
&& isClassComponent()
) {
let current = node;
while (current.type !== 'Program') {
Expand Down Expand Up @@ -170,5 +179,5 @@ module.exports = {
});
}
};
}
})
};
33 changes: 31 additions & 2 deletions tests/lib/rules/no-access-state-in-setstate.js
Expand Up @@ -10,8 +10,8 @@
// ------------------------------------------------------------------------------

const RuleTester = require('eslint').RuleTester;
const rule = require('../../../lib/rules/no-access-state-in-setstate');
const parsers = require('../../helpers/parsers');
const rule = require('../../../lib/rules/no-access-state-in-setstate');

const parserOptions = {
ecmaVersion: 2018,
Expand All @@ -20,11 +20,17 @@ const parserOptions = {
}
};

const settings = {
react: {
createClass: 'createClass'
}
};
jzabala marked this conversation as resolved.
Show resolved Hide resolved

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

const ruleTester = new RuleTester();
const ruleTester = new RuleTester({settings});
ruleTester.run('no-access-state-in-setstate', rule, {
valid: [{
code: [
Expand Down Expand Up @@ -120,6 +126,17 @@ ruleTester.run('no-access-state-in-setstate', rule, {
}
`,
parser: parsers.BABEL_ESLINT
}, {
code: `
class Foo extends Abstract {
update = () => {
const result = this.getResult ( this.state.foo );
return this.setState ({ result });
};
}
`,
parser: parsers.BABEL_ESLINT,
parserOptions
}],

invalid: [{
Expand Down Expand Up @@ -226,5 +243,17 @@ ruleTester.run('no-access-state-in-setstate', rule, {
errors: [{
message: 'Use callback in setState when referencing the previous state.'
}]
}, {
code: `
class Hello extends React.Component {
onClick() {
this.setState(this.state, () => console.log(this.state));
}
}
`,
parserOptions,
errors: [{
message: 'Use callback in setState when referencing the previous state.'
}]
}]
});