Skip to content

Commit c996740

Browse files
authored
Merge pull request #1690 from mindspacepdx/am-should-component-update
[Fix] Rule prop-types includes nextProps checking in shouldComponentUpdate
2 parents e26b7e2 + 8ca344a commit c996740

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

lib/rules/prop-types.js

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,24 @@ module.exports = {
121121
return false;
122122
}
123123

124+
/**
125+
* Check if we are in a class constructor
126+
* @return {boolean} true if we are in a class constructor, false if not
127+
*/
128+
function inShouldComponentUpdate() {
129+
let scope = context.getScope();
130+
while (scope) {
131+
if (
132+
scope.block && scope.block.parent &&
133+
scope.block.parent.key && scope.block.parent.key.name === 'shouldComponentUpdate'
134+
) {
135+
return true;
136+
}
137+
scope = scope.upper;
138+
}
139+
return false;
140+
}
141+
124142
/**
125143
* Checks if a prop is being assigned a value props.bar = 'bar'
126144
* @param {ASTNode} node The AST node being checked.
@@ -146,7 +164,7 @@ module.exports = {
146164
node.object.type === 'ThisExpression' && node.property.name === 'props'
147165
);
148166
const isStatelessFunctionUsage = node.object.name === 'props' && !isAssignmentToProp(node);
149-
const isNextPropsUsage = node.object.name === 'nextProps' && inComponentWillReceiveProps();
167+
const isNextPropsUsage = node.object.name === 'nextProps' && (inComponentWillReceiveProps() || inShouldComponentUpdate());
150168
return isClassUsage || isStatelessFunctionUsage || isNextPropsUsage;
151169
}
152170

@@ -549,7 +567,9 @@ module.exports = {
549567
const isInClassComponent = utils.getParentES6Component() || utils.getParentES5Component();
550568
const isNotInConstructor = !inConstructor();
551569
const isNotInComponentWillReceiveProps = !inComponentWillReceiveProps();
552-
if (isDirectProp && isInClassComponent && isNotInConstructor && isNotInComponentWillReceiveProps) {
570+
const isNotInShouldComponentUpdate = !inShouldComponentUpdate();
571+
if (isDirectProp && isInClassComponent && isNotInConstructor && isNotInComponentWillReceiveProps
572+
&& isNotInShouldComponentUpdate) {
553573
return void 0;
554574
}
555575
if (!isDirectProp) {
@@ -1043,6 +1063,10 @@ module.exports = {
10431063
markPropTypesAsUsed(node);
10441064
}
10451065

1066+
if (node.key.name === 'shouldComponentUpdate' && destructuring) {
1067+
markPropTypesAsUsed(node);
1068+
}
1069+
10461070
if (!node.static || node.kind !== 'get' || !propsUtil.isPropTypesDeclaration(node)) {
10471071
return;
10481072
}

tests/lib/rules/prop-types.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3148,6 +3148,48 @@ ruleTester.run('prop-types', rule, {
31483148
errors: [
31493149
{message: '\'foo\' is missing in props validation'}
31503150
]
3151+
}, {
3152+
code: [
3153+
'class Hello extends Component {',
3154+
' static propTypes = forbidExtraProps({',
3155+
' bar: PropTypes.func',
3156+
' })',
3157+
' shouldComponentUpdate(nextProps) {',
3158+
' if (nextProps.foo) {',
3159+
' return;',
3160+
' }',
3161+
' }',
3162+
' render() {',
3163+
' return <div bar={this.props.bar} />;',
3164+
' }',
3165+
'}'
3166+
].join('\n'),
3167+
parser: 'babel-eslint',
3168+
settings: Object.assign({}, settings, {
3169+
propWrapperFunctions: ['forbidExtraProps']
3170+
}),
3171+
errors: [
3172+
{message: '\'foo\' is missing in props validation'}
3173+
]
3174+
}, {
3175+
code: [
3176+
'class Hello extends Component {',
3177+
' shouldComponentUpdate({foo}) {',
3178+
' if (foo) {',
3179+
' return;',
3180+
' }',
3181+
' }',
3182+
' render() {',
3183+
' return <div bar={this.props.bar} />;',
3184+
' }',
3185+
'}',
3186+
'Hello.propTypes = {',
3187+
' bar: PropTypes.func',
3188+
' }'
3189+
].join('\n'),
3190+
errors: [
3191+
{message: '\'foo\' is missing in props validation'}
3192+
]
31513193
}, {
31523194
code: [
31533195
'class Hello extends React.Component {',

0 commit comments

Comments
 (0)