Skip to content

void-dom-elements-no-children throws a TypeError when installed from the current master branch. #1101

Closed
@phyllisstein

Description

@phyllisstein

Hey there! I hate to be a bother, but I just tried installing this plugin from GitHub, overeager to see if JSX indentation had been improved, and ran into a little trouble linting one of my source files. The void-dom-elements-no-children rule is throwing a TypeError on line 107:

Cannot read property 'value' of undefined
TypeError: Cannot read property 'value' of undefined
    at EventEmitter.CallExpression (/Users/daniel/Repos/Ignota/rupertsberg/node_modules/eslint-plugin-react/lib/rules/void-dom-elements-no-children.js:107:34)
    at emitOne (events.js:101:20)
    at EventEmitter.emit (events.js:191:7)
    at NodeEventGenerator.enterNode (/Users/daniel/Repos/Ignota/rupertsberg/node_modules/eslint/lib/util/node-event-generator.js:39:22)
    at CodePathAnalyzer.enterNode (/Users/daniel/Repos/Ignota/rupertsberg/node_modules/eslint/lib/code-path-analysis/code-path-analyzer.js:607:23)
    at CommentEventGenerator.enterNode (/Users/daniel/Repos/Ignota/rupertsberg/node_modules/eslint/lib/util/comment-event-generator.js:98:23)
    at Controller.enter (/Users/daniel/Repos/Ignota/rupertsberg/node_modules/eslint/lib/eslint.js:928:36)
    at Controller.__execute (/Users/daniel/Repos/Ignota/rupertsberg/node_modules/estraverse/estraverse.js:397:31)
    at Controller.traverse (/Users/daniel/Repos/Ignota/rupertsberg/node_modules/estraverse/estraverse.js:501:28)
    at Controller.Traverser.controller.traverse (/Users/daniel/Repos/Ignota/rupertsberg/node_modules/eslint/lib/util/traverser.js:36:33)

Logging node.arguments shows that it's an empty array just before the crash, but honest I don't know nearly enough about your lovely linter's deep magic to say any more than that. Please let me know if it'd be helpful to Gist the source file, though, or if I can furnish any other information I've got. Disabling the rule in my ESLint config stops the crash for now.

Activity

ljharb

ljharb commented on Mar 5, 2017

@ljharb
Member

It would absolutely be helpful to gist the source file it crashes on, thanks!

phyllisstein

phyllisstein commented on Mar 5, 2017

@phyllisstein
Author

Sure thing! Went ahead and dumped the JSX, my .eslintrc.yml, and the error here: https://gist.github.com/phyllisstein/04036a187aa4c2d4195a67cefb4170cb. Let me know if you need anything else!

phyllisstein

phyllisstein commented on Mar 5, 2017

@phyllisstein
Author

So I did a little ham-handed investigation and started deleting lines blindly. Turns out it's the handleClick function? Including any of the lines in the range https://gist.github.com/phyllisstein/04036a187aa4c2d4195a67cefb4170cb#file-button-jsx-L58-L64 causes it to throw, whereas deleting it entirely seems to work around the issue. Heaven knows what that portends though.

ljharb

ljharb commented on Mar 5, 2017

@ljharb
Member

Interesting - probably because it's an arrow function class property. If instead (which would be much more performant) it was a true instance method, and you did this.handleClick = this.handleClick.bind(this) in the constructor, I suspect it'd work.

Thanks though, this should be very helpful to fix the bug.

Hypnosphi

Hypnosphi commented on Apr 25, 2017

@Hypnosphi
Contributor

which would be much more performant

Why exactly? You still create a bound function in constructor, that's roughly what arrow function property compiles to

ljharb

ljharb commented on Apr 25, 2017

@ljharb
Member

Yes, in the constructor once, instead of thousands of times once per render.

timhwang21

timhwang21 commented on Apr 25, 2017

@timhwang21

I thought if the arrow function is a class property, it is also only computed once?

class Foo extends Component {
  myArrowFunc = () => { ... }
}

Din't think @Hypnosphi is talking about arrow functions within render().

ljharb

ljharb commented on Apr 25, 2017

@ljharb
Member

Yes, that's true. But at that point the meat of the function isn't in an optimized prototype method, its newly created on every render. Constructor-bound prototype methods are the best approach.

timhwang21

timhwang21 commented on Apr 25, 2017

@timhwang21

I didn't know that, thanks! Fixes an incorrect belief of mine.

Hypnosphi

Hypnosphi commented on Apr 25, 2017

@Hypnosphi
Contributor
class Foo {
  myArrowFunc = () => { ... }
}

compiles to

class Foo {
  constructor() {
    this.myArrowFunc = () => { ... };
  }
}

Excuse me, but I don't see any rendering here. Did you mean "on every constructor call" instead? Then it shouldn't occur too often in a typical react app.

ljharb

ljharb commented on Apr 25, 2017

@ljharb
Member

@Hypnosphi yes, you're right that your example isn't about the render path. However, #1101 (comment) still applies.

52 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @ljharb@phyllisstein@timhwang21@Hypnosphi

        Issue actions

          void-dom-elements-no-children throws a TypeError when installed from the current master branch. · Issue #1101 · jsx-eslint/eslint-plugin-react