Skip to content

Commit

Permalink
Merge pull request #2359 from golopot/fix-props-setstate-updater
Browse files Browse the repository at this point in the history
[fix] `prop-types`: false positive with setState updater
  • Loading branch information
ljharb committed Jul 28, 2019
2 parents 47c4c8b + dcf9766 commit 60d502d
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 21 deletions.
33 changes: 12 additions & 21 deletions lib/util/usedPropTypes.js
Expand Up @@ -135,25 +135,16 @@ function isInLifeCycleMethod(node, checkAsyncSafeLifeCycles) {
}

/**
* Check if the current node is in a setState updater method
* @return {boolean} true if we are in a setState updater, false if not
* Check if a function node is a setState updater
* @param {ASTNode} node a function node
* @return {boolean}
*/
function inSetStateUpdater(context) {
let scope = context.getScope();
while (scope) {
if (
scope.block && scope.block.parent &&
scope.block.parent.type === 'CallExpression' &&
scope.block.parent.callee.property &&
scope.block.parent.callee.property.name === 'setState' &&
// Make sure we are in the updater not the callback
scope.block.parent.arguments[0].start === scope.block.start
) {
return true;
}
scope = scope.upper;
}
return false;
function isSetStateUpdater(node) {
return node.parent.type === 'CallExpression' &&
node.parent.callee.property &&
node.parent.callee.property.name === 'setState' &&
// Make sure we are in the updater not the callback
node.parent.arguments[0] === node;
}

function isPropArgumentInSetStateUpdater(context, name) {
Expand Down Expand Up @@ -324,7 +315,7 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
break;
}
type = 'destructuring';
const propParam = inSetStateUpdater(context) ? node.params[1] : node.params[0];
const propParam = isSetStateUpdater(node) ? node.params[1] : node.params[0];
properties = propParam.type === 'AssignmentPattern' ?
propParam.left.properties :
propParam.properties;
Expand Down Expand Up @@ -399,7 +390,7 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
* FunctionDeclaration, or FunctionExpression
*/
function markDestructuredFunctionArgumentsAsUsed(node) {
const param = node.params && inSetStateUpdater(context) ? node.params[1] : node.params[0];
const param = node.params && isSetStateUpdater(node) ? node.params[1] : node.params[0];

const destructuring = param && (
param.type === 'ObjectPattern' ||
Expand All @@ -412,7 +403,7 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
}

function handleSetStateUpdater(node) {
if (!node.params || node.params.length < 2 || !inSetStateUpdater(context)) {
if (!node.params || node.params.length < 2 || !isSetStateUpdater(node)) {
return;
}
markPropTypesAsUsed(node);
Expand Down
11 changes: 11 additions & 0 deletions tests/lib/rules/prop-types.js
Expand Up @@ -2065,6 +2065,17 @@ ruleTester.run('prop-types', rule, {
};
`
},
{
code: `
class Foo extends React.Component {
bar() {
this.setState((state, props) => {
function f(_, {aaaaaaa}) {}
});
}
}
`
},
{
code: `
class Foo extends React.Component {
Expand Down

0 comments on commit 60d502d

Please sign in to comment.