Skip to content

Commit 860ebea

Browse files
vedadeeptaljharb
authored andcommitted
[Fix] destructuring-assignment, no-multi-comp, no-unstable-nested-components, component detection: improve component detection
1 parent faadccb commit 860ebea

File tree

5 files changed

+96
-18
lines changed

5 files changed

+96
-18
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
66
## Unreleased
77

88
### Fixed
9-
* component detection: use `estraverse` to improve component detection ([#2992][] @Wesitos)
9+
* component detection: use `estraverse` to improve component detection ([#2992][] @Wesitos)
10+
* [`destructuring-assignment`], [`no-multi-comp`], [`no-unstable-nested-components`], component detection: improve component detection ([#3001][] @vedadeepta)
1011

1112
### Changed
1213
* [Docs] [`jsx-no-bind`]: updates discussion of refs ([#2998][] @dimitropoulos)
1314

15+
[#3001]: https://github.com/yannickcr/eslint-plugin-react/pull/3001
1416
[#2998]: https://github.com/yannickcr/eslint-plugin-react/pull/2998
1517
[#2992]: https://github.com/yannickcr/eslint-plugin-react/pull/2992
1618

lib/util/Components.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,8 @@ function componentRule(rule, context) {
651651
return undefined;
652652
}
653653
if (utils.isInAllowedPositionForComponent(node) && utils.isReturningJSXOrNull(node)) {
654+
if (utils.isParentComponentNotStatelessComponent(node)) return undefined;
655+
654656
const isMethod = node.parent.type === 'Property' && node.parent.method;
655657

656658
if (isMethod && !isFirstLetterCapitalized(node.parent.key.name)) {
@@ -798,6 +800,18 @@ function componentRule(rule, context) {
798800

799801
// Return the component
800802
return components.add(componentNode, 1);
803+
},
804+
805+
isParentComponentNotStatelessComponent(node) {
806+
return (
807+
node.parent
808+
&& node.parent.key
809+
&& node.parent.key.type === 'Identifier'
810+
// custom component functions must start with a capital letter (returns false otherwise)
811+
&& node.parent.key.name.charAt(0) === node.parent.key.name.charAt(0).toLowerCase()
812+
// react render function cannot have params
813+
&& !!(node.params || []).length
814+
);
801815
}
802816
};
803817

@@ -846,6 +860,7 @@ function componentRule(rule, context) {
846860
components.add(node, 0);
847861
return;
848862
}
863+
849864
const component = utils.getParentComponent();
850865
if (
851866
!component
@@ -863,6 +878,7 @@ function componentRule(rule, context) {
863878
components.add(node, 0);
864879
return;
865880
}
881+
866882
node = utils.getParentComponent();
867883
if (!node) {
868884
return;
@@ -875,7 +891,9 @@ function componentRule(rule, context) {
875891
components.add(node, 0);
876892
return;
877893
}
894+
878895
const component = utils.getParentComponent();
896+
879897
if (
880898
!component
881899
|| (component.parent && component.parent.type === 'JSXExpressionContainer')

tests/lib/rules/destructuring-assignment.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,43 @@ ruleTester.run('destructuring-assignment', rule, {
196196
},
197197
};
198198
`
199+
}, {
200+
code: `
201+
const columns = [
202+
{
203+
render: (val) => {
204+
if (val.url) {
205+
return (
206+
<a href={val.url}>
207+
{val.test}
208+
</a>
209+
);
210+
}
211+
return null;
212+
},
213+
},
214+
];
215+
`
216+
}, {
217+
code: `
218+
const columns = [
219+
{
220+
render: val => <span>{val}</span>,
221+
},
222+
{
223+
someRenderFunc: function(val) {
224+
if (val.url) {
225+
return (
226+
<a href={val.url}>
227+
{val.test}
228+
</a>
229+
);
230+
}
231+
return null;
232+
},
233+
},
234+
];
235+
`
199236
}],
200237

201238
invalid: [{
@@ -353,5 +390,27 @@ ruleTester.run('destructuring-assignment', rule, {
353390
messageId: 'noDestructAssignment',
354391
data: {type: 'state'}
355392
}]
393+
}, {
394+
code: `
395+
const columns = [
396+
{
397+
CustomComponentName: function(props) {
398+
if (props.url) {
399+
return (
400+
<a href={props.url}>
401+
{props.test}
402+
</a>
403+
);
404+
}
405+
return null;
406+
},
407+
},
408+
];
409+
`,
410+
parser: parsers.BABEL_ESLINT,
411+
errors: [{
412+
messageId: 'useDestructAssignment',
413+
data: {type: 'props'}
414+
}]
356415
}]
357416
});

tests/lib/rules/no-multi-comp.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,11 +316,11 @@ ruleTester.run('no-multi-comp', rule, {
316316
}, {
317317
code: [
318318
'export default {',
319-
' renderHello(props) {',
319+
' RenderHello(props) {',
320320
' let {name} = props;',
321321
' return <div>{name}</div>;',
322322
' },',
323-
' renderHello2(props) {',
323+
' RenderHello2(props) {',
324324
' let {name} = props;',
325325
' return <div>{name}</div>;',
326326
' }',

tests/lib/rules/no-unstable-nested-components.js

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,20 @@ ruleTester.run('no-unstable-nested-components', rule, {
490490
},
491491
});
492492
`
493+
},
494+
{
495+
code: `
496+
function ParentComponent() {
497+
const rows = [
498+
{
499+
name: 'A',
500+
notPrefixedWithRender: (props) => <Row {...props} />
501+
},
502+
];
503+
504+
return <Table rows={rows} />;
505+
}
506+
`
493507
}
494508
/* TODO These minor cases are currently falsely marked due to component detection
495509
{
@@ -1010,21 +1024,6 @@ ruleTester.run('no-unstable-nested-components', rule, {
10101024
`,
10111025
errors: [{message: ERROR_MESSAGE_COMPONENT_AS_PROPS}]
10121026
},
1013-
{
1014-
code: `
1015-
function ParentComponent() {
1016-
const rows = [
1017-
{
1018-
name: 'A',
1019-
notPrefixedWithRender: (props) => <Row {...props} />
1020-
},
1021-
];
1022-
1023-
return <Table rows={rows} />;
1024-
}
1025-
`,
1026-
errors: [{message: ERROR_MESSAGE}]
1027-
},
10281027
{
10291028
code: `
10301029
class ParentComponent extends React.Component {

0 commit comments

Comments
 (0)