Skip to content

Commit 78e9ea7

Browse files
authored
Merge pull request #2084 from jomasti/issue-2076
Handle functional setState in no-unused-state
2 parents 8ef86c5 + 1a1a3a2 commit 78e9ea7

File tree

2 files changed

+98
-3
lines changed

2 files changed

+98
-3
lines changed

lib/rules/no-unused-state.js

+19-3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ function getInitialClassInfo() {
5959
};
6060
}
6161

62+
function isSetStateCall(node) {
63+
return (
64+
node.callee.type === 'MemberExpression' &&
65+
isThisExpression(node.callee.object) &&
66+
getName(node.callee.property) === 'setState'
67+
);
68+
}
69+
6270
module.exports = {
6371
meta: {
6472
docs: {
@@ -246,13 +254,21 @@ module.exports = {
246254
// If we're looking at a `this.setState({})` invocation, record all the
247255
// properties as state fields.
248256
if (
249-
node.callee.type === 'MemberExpression' &&
250-
isThisExpression(node.callee.object) &&
251-
getName(node.callee.property) === 'setState' &&
257+
isSetStateCall(node) &&
252258
node.arguments.length > 0 &&
253259
node.arguments[0].type === 'ObjectExpression'
254260
) {
255261
addStateFields(node.arguments[0]);
262+
} else if (
263+
isSetStateCall(node) &&
264+
node.arguments.length > 0 &&
265+
node.arguments[0].type === 'ArrowFunctionExpression' &&
266+
node.arguments[0].body.type === 'ObjectExpression'
267+
) {
268+
if (node.arguments[0].params.length > 0) {
269+
classInfo.aliases.add(getName(node.arguments[0].params[0]));
270+
}
271+
addStateFields(node.arguments[0].body);
256272
}
257273
},
258274

tests/lib/rules/no-unused-state.js

+79
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,66 @@ eslintTester.run('no-unused-state', rule, {
576576
}
577577
}`,
578578
parser: 'babel-eslint'
579+
}, {
580+
code: `
581+
class Foo extends Component {
582+
state = {
583+
initial: 'foo',
584+
}
585+
handleChange = () => {
586+
this.setState(state => ({
587+
current: state.initial
588+
}));
589+
}
590+
render() {
591+
const { current } = this.state;
592+
return <div>{current}</div>
593+
}
594+
}
595+
`,
596+
parser: 'babel-eslint'
597+
}, {
598+
code: `
599+
class Foo extends Component {
600+
constructor(props) {
601+
super(props);
602+
this.state = {
603+
initial: 'foo',
604+
}
605+
}
606+
handleChange = () => {
607+
this.setState(state => ({
608+
current: state.initial
609+
}));
610+
}
611+
render() {
612+
const { current } = this.state;
613+
return <div>{current}</div>
614+
}
615+
}
616+
`,
617+
parser: 'babel-eslint'
618+
}, {
619+
code: `
620+
class Foo extends Component {
621+
constructor(props) {
622+
super(props);
623+
this.state = {
624+
initial: 'foo',
625+
}
626+
}
627+
handleChange = () => {
628+
this.setState((state, props) => ({
629+
current: state.initial
630+
}));
631+
}
632+
render() {
633+
const { current } = this.state;
634+
return <div>{current}</div>
635+
}
636+
}
637+
`,
638+
parser: 'babel-eslint'
579639
}
580640
],
581641

@@ -914,6 +974,25 @@ eslintTester.run('no-unused-state', rule, {
914974
}`,
915975
errors: getErrorMessages(['id']),
916976
parser: 'babel-eslint'
977+
}, {
978+
code: `
979+
class Foo extends Component {
980+
state = {
981+
initial: 'foo',
982+
}
983+
handleChange = () => {
984+
this.setState(() => ({
985+
current: 'hi'
986+
}));
987+
}
988+
render() {
989+
const { current } = this.state;
990+
return <div>{current}</div>
991+
}
992+
}
993+
`,
994+
parser: 'babel-eslint',
995+
errors: getErrorMessages(['initial'])
917996
}
918997
]
919998
});

0 commit comments

Comments
 (0)