Skip to content

Commit 0ddcd35

Browse files
committed
fix: report when required props have default value
1 parent 3c1d520 commit 0ddcd35

File tree

2 files changed

+65
-8
lines changed

2 files changed

+65
-8
lines changed

lib/rules/require-default-props.js

+23-8
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ module.exports = {
106106
});
107107
}
108108

109+
function isPropWithNoDefaulVal(prop) {
110+
if (prop.type === 'RestElement' || prop.type === 'ExperimentalRestProperty') {
111+
return false;
112+
}
113+
return prop.value.type !== 'AssignmentPattern';
114+
}
115+
109116
/**
110117
* If functions option is 'defaultArguments', reports defaultProps is used and all params that doesn't initialized.
111118
* @param {Object} componentNode Node of component.
@@ -134,15 +141,23 @@ module.exports = {
134141
});
135142
}
136143
} else if (props.type === 'ObjectPattern') {
144+
// Filter required props with default value and report error
137145
props.properties.filter((prop) => {
138-
if (prop.type === 'RestElement' || prop.type === 'ExperimentalRestProperty') {
139-
return false;
140-
}
141-
const propType = propTypes[prop.key.name];
142-
if (!propType || propType.isRequired) {
143-
return false;
144-
}
145-
return prop.value.type !== 'AssignmentPattern';
146+
const propName = prop && prop.key && prop.key.name;
147+
const isPropRequired = propTypes[propName] && propTypes[propName].isRequired;
148+
return propTypes[propName] && isPropRequired && !isPropWithNoDefaulVal(prop);
149+
}).forEach((prop) => {
150+
report(context, messages.noDefaultWithRequired, 'noDefaultWithRequired', {
151+
node: prop,
152+
data: { name: prop.key.name },
153+
});
154+
});
155+
156+
// Filter non required props with no default value and report error
157+
props.properties.filter((prop) => {
158+
const propName = prop && prop.key && prop.key.name;
159+
const isPropRequired = propTypes[propName] && propTypes[propName].isRequired;
160+
return propTypes[propName] && !isPropRequired && isPropWithNoDefaulVal(prop);
146161
}).forEach((prop) => {
147162
report(context, messages.shouldAssignObjectDefault, 'shouldAssignObjectDefault', {
148163
node: prop,

tests/lib/rules/require-default-props.js

+42
Original file line numberDiff line numberDiff line change
@@ -3066,5 +3066,47 @@ ruleTester.run('require-default-props', rule, {
30663066
propWrapperFunctions: ['forbidExtraProps'],
30673067
},
30683068
},
3069+
{
3070+
code: `
3071+
function MyStatelessComponent({ foo = 'foo' }) {
3072+
return <div>{foo}{bar}</div>;
3073+
}
3074+
MyStatelessComponent.propTypes = {
3075+
foo: PropTypes.string.isRequired,
3076+
};
3077+
`,
3078+
options: [{ functions: 'defaultArguments' }],
3079+
errors: [
3080+
{
3081+
messageId: 'noDefaultWithRequired',
3082+
data: { name: 'foo' },
3083+
line: 2,
3084+
},
3085+
],
3086+
},
3087+
{
3088+
code: `
3089+
function MyStatelessComponent({ foo = 'foo', bar }) {
3090+
return <div>{foo}{bar}</div>;
3091+
}
3092+
MyStatelessComponent.propTypes = {
3093+
foo: PropTypes.string.isRequired,
3094+
bar: PropTypes.string
3095+
};
3096+
`,
3097+
options: [{ functions: 'defaultArguments' }],
3098+
errors: [
3099+
{
3100+
messageId: 'noDefaultWithRequired',
3101+
data: { name: 'foo' },
3102+
line: 2,
3103+
},
3104+
{
3105+
messageId: 'shouldAssignObjectDefault',
3106+
data: { name: 'bar' },
3107+
line: 2,
3108+
},
3109+
],
3110+
},
30693111
]),
30703112
});

0 commit comments

Comments
 (0)