Skip to content

Commit a908eb3

Browse files
authored
Merge pull request #1598 from jaaberg/master
Find edge case in no-access-state-in-setstate (#1597)
2 parents 292ebed + 4950623 commit a908eb3

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

lib/rules/no-access-state-in-setstate.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ module.exports = {
107107
if (current.type === 'VariableDeclarator') {
108108
vars.push({
109109
node: node,
110-
scope: context.getScope()
110+
scope: context.getScope(),
111+
variableName: current.id.name
111112
});
112113
break;
113114
}
@@ -123,11 +124,14 @@ module.exports = {
123124
while (current.parent.type === 'BinaryExpression') {
124125
current = current.parent;
125126
}
126-
if (current.parent.value === current) {
127+
if (
128+
current.parent.value === current ||
129+
current.parent.object === current
130+
) {
127131
while (current.type !== 'Program') {
128132
if (isSetStateCall(current)) {
129133
vars
130-
.filter(v => v.scope === context.getScope())
134+
.filter(v => v.scope === context.getScope() && v.variableName === node.name)
131135
.map(v => context.report(
132136
v.node,
133137
'Use callback in setState when referencing the previous state.'
@@ -136,6 +140,19 @@ module.exports = {
136140
current = current.parent;
137141
}
138142
}
143+
},
144+
145+
ObjectPattern(node) {
146+
const isDerivedFromThis = node.parent.init.type === 'ThisExpression';
147+
node.properties.forEach(property => {
148+
if (property.key.name === 'state' && isDerivedFromThis) {
149+
vars.push({
150+
node: property.key,
151+
scope: context.getScope(),
152+
variableName: property.key.name
153+
});
154+
}
155+
});
139156
}
140157
};
141158
}

tests/lib/rules/no-access-state-in-setstate.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ ruleTester.run('no-access-state-in-setstate', rule, {
6464
});
6565
`,
6666
parserOptions: parserOptions
67+
}, {
68+
code: [
69+
'var Hello = React.createClass({',
70+
' onClick: function() {',
71+
' var nextValueNotUsed = this.state.value + 1',
72+
' var nextValue = 2',
73+
' this.setState({value: nextValue})',
74+
' }',
75+
'});'
76+
].join('\n'),
77+
parserOptions: parserOptions
6778
}],
6879

6980
invalid: [{
@@ -103,6 +114,19 @@ ruleTester.run('no-access-state-in-setstate', rule, {
103114
errors: [{
104115
message: 'Use callback in setState when referencing the previous state.'
105116
}]
117+
}, {
118+
code: [
119+
'var Hello = React.createClass({',
120+
' onClick: function() {',
121+
' var {state} = this',
122+
' this.setState({value: state.value + 1})',
123+
' }',
124+
'});'
125+
].join('\n'),
126+
parserOptions: parserOptions,
127+
errors: [{
128+
message: 'Use callback in setState when referencing the previous state.'
129+
}]
106130
}, {
107131
code: [
108132
'function nextState(state) {',

0 commit comments

Comments
 (0)