In the class below:
class TestComponent extends React.Component {
static defaultProps = function () {
const date = new Date();
return {
date
};
}();
}
the defaultProps are equal to a anonymous function return value.
In this case, the eslint-plugin-react doesn't run, and throws the following error:
TypeError: Cannot read property 'split' of undefined
at Object.isPropWrapperFunction (~/project/node_modules/eslint-plugin-react/lib/util/propWrapper.js:12:26)
at resolveNodeValue (~/project/node_modules/eslint-plugin-react/lib/util/defaultProps.js:30:23)
at Object.ClassProperty (~/project/node_modules/eslint-plugin-react/lib/util/defaultProps.js:222:26)
at updatedRuleInstructions.(anonymous function) (~/project/node_modules/eslint-plugin-react/lib/util/Components.js:752:46)
at listeners.(anonymous function).forEach.listener (~/project/node_modules/eslint/lib/util/safe-emitter.js:45:58)
I'm using the following versions:
"eslint": "5.10.0"
"eslint-plugin-react": "7.11.1".
If in the same class I put the defaultProps equal do an object it runs as expected.
Thanks
The rule definitely shouldn't crash - but static defaultProps can only ever be an object literal, not a function. The legacy createReactClass pattern is the one that had a function for things like that.
Can you update to v7.12.1 and see if it's still crashing?
Also, do you know what rule it's crashing on?
@ljharb this is an IIFE though, so it should still work out? Pretty rare case though and not something we can lint for IMO (shouldn't crash of course though).
Ah, I didn't even see that - yes, the IIFE should work fine wrt React.
I'm also getting this with latest
"eslint": "5.11.1",
"eslint-plugin-react": "7.12.1",
Setting this in .eslintrc.yaml is my work-around
react/forbid-prop-types: 0
ST:
> node ./node_modules/eslint/bin/eslint.js --ext .js,.jsx .
TypeError: Cannot read property 'split' of undefined
at Object.isPropWrapperFunction (/project/node_modules/eslint-plugin-react/lib/util/propWrapper.js:12:26)
at checkNode (/project/node_modules/eslint-plugin-react/lib/rules/forbid-prop-types.js:128:31)
at MemberExpression (/project/node_modules/eslint-plugin-react/lib/rules/forbid-prop-types.js:158:9)
at listeners.(anonymous function).forEach.listener (/project/node_modules/eslint/lib/util/safe-emitter.js:45:58)
at Array.forEach (<anonymous>)
at Object.emit (/project/node_modules/eslint/lib/util/safe-emitter.js:45:38)
at NodeEventGenerator.applySelector (/project/node_modules/eslint/lib/util/node-event-generator.js:251:26)
at NodeEventGenerator.applySelectors (/project/node_modules/eslint/lib/util/node-event-generator.js:280:22)
at NodeEventGenerator.enterNode (/project/node_modules/eslint/lib/util/node-event-generator.js:294:14)
at CodePathAnalyzer.enterNode (/project/node_modules/eslint/lib/code-path-analysis/code-path-analyzer.js:632:23)
@jethrolarson by any chance, can you share the code that it's erroring on?
Stack trace doesn't say where the actual problem is, so I'm not sure. Code is proprietary so I can't just share the project.
The OP's test code doesn't crash on master.
@jethrolarson I understand. if you edit lib/rules/forbid-prop-types.js line 128 to console.log(context.getFilename()) (i think), it should print out the file at least?
@ljharb just throwing it out there - would it be impossible for eslint to set an uncaught exception handler that would make it easier for people to locate the source of crashes? We've been getting a lot of reports like this recently. (also sorry for having caused some of them with my changes)
I suppose we could; it'd be pretty intrusive to other plugins tho. It seems more like something eslint itself should be handing.
File with error (i think):
HeroTeaserList.propTypes = Object.assign({
heroIndex: PropTypes.number,
preview: PropTypes.bool,
}, componentApi, teaserListProps);
in another file
export const componentConfiguration = {
childComponentMapping: objectOf(string),
componentConfig: object,
componentInstanceId: string,
componentType: string,
dataType: string,
filter: shape(TemplateFilter),
filterVersionSetUuid: string,
teasers: arrayOf(shape(TeaserContent)),
title: string,
titleOverride: node,
uuid: string.isRequired,
visibleCount: number,
epgUuid: string,
readOnly: bool,
};
export const componentApi = Object.assign({
getComponent: func.isRequired,
onNavigation: func,
onConfigurationChange: func,
}, componentConfiguration);
another file
export const teaserListProps = {
'componentInstanceId': string,
'title': string.isRequired,
'uuid': string.isRequired,
'data': object,
'listSize': number,
'priority': number,
'teasers': arrayOf(shape(teaserProps)).isRequired,
'visibleCount': number,
};
Perfect, I'm able to repro.
@ljharb yeah that's what I meant there; just thought you might know why that could be unrealistic. I'll look around their issue tracker. 馃憤
This fails now even with the newest version 7.12.2:
RowSpanTable.propTypes = Object.assign({}, Table.propTypes, {
propertyOrder: PropTypes.arrayOf(PropTypes.string).isRequired,
});
RowSpanTable.defaultProps = Object.assign({}, Table.defaultProps, {
propertyOrder: [],
});
Table.propTypes = {
pageOfItems: PropTypes.arrayOf(PropTypes.object).isRequired,
onHeadlineClickedHandler: PropTypes.func.isRequired,
sortByColumn: PropTypes.string.isRequired,
getClassNameForHeadline: PropTypes.func.isRequired,
headers: PropTypes.arrayOf(PropTypes.instanceOf(JSModelTableHeader)).isRequired, // array of JSModelTableHeader
noItemFoundMessage: PropTypes.string.isRequired,
rowClass: PropTypes.func.isRequired, // e.g. MetricRow
rowProps: PropTypes.object.isRequired,
rowItemKey: PropTypes.string.isRequired, // the key property of the item
};
Table.defaultProps = {
pageOfItems: [],
};
Had to disable the PropTypes check for now.
@murphy1312 can you file a new issue?
Most helpful comment
Perfect, I'm able to repro.