diff --git a/lib/rules/require-default-props.js b/lib/rules/require-default-props.js index d1b27eefe1..13fc557ef0 100644 --- a/lib/rules/require-default-props.js +++ b/lib/rules/require-default-props.js @@ -106,6 +106,13 @@ module.exports = { }); } + function isPropWithNoDefaulVal(prop) { + if (prop.type === 'RestElement' || prop.type === 'ExperimentalRestProperty') { + return false; + } + return prop.value.type !== 'AssignmentPattern'; + } + /** * If functions option is 'defaultArguments', reports defaultProps is used and all params that doesn't initialized. * @param {Object} componentNode Node of component. @@ -134,15 +141,23 @@ module.exports = { }); } } else if (props.type === 'ObjectPattern') { + // Filter required props with default value and report error props.properties.filter((prop) => { - if (prop.type === 'RestElement' || prop.type === 'ExperimentalRestProperty') { - return false; - } - const propType = propTypes[prop.key.name]; - if (!propType || propType.isRequired) { - return false; - } - return prop.value.type !== 'AssignmentPattern'; + const propName = prop && prop.key && prop.key.name; + const isPropRequired = propTypes[propName] && propTypes[propName].isRequired; + return propTypes[propName] && isPropRequired && !isPropWithNoDefaulVal(prop); + }).forEach((prop) => { + report(context, messages.noDefaultWithRequired, 'noDefaultWithRequired', { + node: prop, + data: { name: prop.key.name }, + }); + }); + + // Filter non required props with no default value and report error + props.properties.filter((prop) => { + const propName = prop && prop.key && prop.key.name; + const isPropRequired = propTypes[propName] && propTypes[propName].isRequired; + return propTypes[propName] && !isPropRequired && isPropWithNoDefaulVal(prop); }).forEach((prop) => { report(context, messages.shouldAssignObjectDefault, 'shouldAssignObjectDefault', { node: prop, diff --git a/tests/lib/rules/require-default-props.js b/tests/lib/rules/require-default-props.js index 8ba5d53d7c..d389cd7217 100644 --- a/tests/lib/rules/require-default-props.js +++ b/tests/lib/rules/require-default-props.js @@ -3066,5 +3066,47 @@ ruleTester.run('require-default-props', rule, { propWrapperFunctions: ['forbidExtraProps'], }, }, + { + code: ` + function MyStatelessComponent({ foo = 'foo' }) { + return
{foo}{bar}
; + } + MyStatelessComponent.propTypes = { + foo: PropTypes.string.isRequired, + }; + `, + options: [{ functions: 'defaultArguments' }], + errors: [ + { + messageId: 'noDefaultWithRequired', + data: { name: 'foo' }, + line: 2, + }, + ], + }, + { + code: ` + function MyStatelessComponent({ foo = 'foo', bar }) { + return
{foo}{bar}
; + } + MyStatelessComponent.propTypes = { + foo: PropTypes.string.isRequired, + bar: PropTypes.string + }; + `, + options: [{ functions: 'defaultArguments' }], + errors: [ + { + messageId: 'noDefaultWithRequired', + data: { name: 'foo' }, + line: 2, + }, + { + messageId: 'shouldAssignObjectDefault', + data: { name: 'bar' }, + line: 2, + }, + ], + }, ]), });