blueprint: @HotkeysTarget TypeError: class constructors must be invoked with |new|

Environment

  • Package version(s): “@blueprintjs/core”: “^3.15.1”, “typescript”: “3.5.1”
  • Browser and OS versions: Ubuntu 18.04, FireFox 67.0.2

Steps to reproduce

import { Hotkey, Hotkeys, HotkeysTarget } from "@blueprintjs/core";
@HotkeysTarget
export class MyComponent extends React.PureComponent<{}> {
     public render () { return <div>Hello there</div> };
     public renderHotkeys() {
        return <Hotkeys>
            <Hotkey
                combo="up"
                label="Up"
                onKeyDown={() => { alert('Need to go up'); } }
            />
        </Hotkeys>;
    }    
}

Actual behavior

The component cannot be rendered. I get an error that starts with this:


TypeError: class constructors must be invoked with |new|
HotkeysTargetClass
node_modules/@blueprintjs/core/lib/esm/components/hotkeys/hotkeysTarget.js:32

  29 | tslib_1.__extends(HotkeysTargetClass, _super);
  30 | 
  31 | function HotkeysTargetClass() {
> 32 |   return _super !== null && _super.apply(this, arguments) || this;
     | ^  33 | }
  34 | 
  35 | HotkeysTargetClass.prototype.componentWillMount = function () {

Full traceback available, but probably not needed.

Expected behavior

The component should be rendered and the hotkey should be working.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 7
  • Comments: 34 (17 by maintainers)

Commits related to this issue

Most upvoted comments

I met the same error (but I dont use TS, just ES6 + webpack + babel).

HotkeysTargetClass() { 
    return _super !== null && _super.apply(this, arguments) || this; 
}

This is a tanspiled to ES5 HotkeysTargetClass class constuctor. The problem is that it expects _super (which is WrappedComponent actually) to be a function (ES5-style class). If in your code WrappedComponent is a ES6 class, it throws an error.

I solved it by using packages/core/lib/esnext/components/hotkeys/hotkeysTarget.js instead of packages/core/lib/esm/components/hotkeys/hotkeysTarget.js, because HotkeysTargetClass is declared in modern way there:

return _a = class HotkeysTargetClass extends WrappedComponent {
   ...
}

I’m working on this as part of Blueprint v4.0 changes, it’s the next thing on my list, should be able to prototype something later this week.

Some thoughts on this: Create React App does not support decorators by default, see here.

I propose just moving away from decorators for now, as many libraries (e.g. MobX) have done, or at least adding another option for users to declare HotKeys, maybe a React hook.

@sgaloux I second you.

Used create-react-app --typescript in my project, I checked I have the same blueprint and react versions as the codesandbox thing, yet I get the error in my project.

Also having es5 as target.

In my personal opinion, I think that an ideal fix would be HOC versions of HotkeysTarget and ContextMenuTarget, and to possibly deprecate the existing decorator versions. This would remove any need to change configs to use them and would be more ‘reactish’. Using class decorators across a module boundary gets really messy if one side is polyfilling classes. Hooks may also be a good fit here, but I think blueprint supports react 15, so that would be a no go.

This seems like the best solution to me as well. I use nwb on top of webpack and don’t feel like digging into the babel stuff right now so just downgraded nwb to a previous version where everything was working. This is fine for the time being but it would be great to have a simple HOC solution.

@maclockard here’s what I see when I tried:

import {HotkeysTarget} from '@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysTarget.js';
 ERROR  in ./node_modules/@blueprintjs/core/lib/esnext/components/button/buttons.js 29:38
Module parse failed: Unexpected token (29:38)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|             : (ref) => {
|                 this.buttonRef = ref;
>                 this.props.elementRef?.(ref);
|             };
|     }
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/toast/toast.js 24:0-57 48:36-42 72:39-51
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/index.js
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysDialog.js
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysEvents.js
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysTarget.js
 @ ./src/withEditorInteractions/createSequenceInputPopup.js
 @ ./src/withEditorInteractions/index.js
 @ ./src/index.js
 @ ./demo/src/index.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ReactRefreshEntry.js (webpack)-dev-server/client?http://localhost:3344/ ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ErrorOverlayEntry.js (webpack)/hot/only-dev-server.js ./demo/src/index.js

 ERROR  in ./node_modules/@blueprintjs/core/lib/esnext/components/forms/asyncControllableInput.js 45:42
Module parse failed: Unexpected token (45:42)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|                 localValue: this.state.externalValue,
|             });
>             this.props.onCompositionStart?.(e);
|         };
|         this.handleCompositionEnd = (e) => {
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/forms/inputGroup.js 24:0-66 50:32-54
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/index.js
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysDialog.js
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysEvents.js
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysTarget.js
 @ ./src/withEditorInteractions/createSequenceInputPopup.js
 @ ./src/withEditorInteractions/index.js
 @ ./src/index.js
 @ ./demo/src/index.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ReactRefreshEntry.js (webpack)-dev-server/client?http://localhost:3344/ ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ErrorOverlayEntry.js (webpack)/hot/only-dev-server.js ./demo/src/index.js

 ERROR  in ./node_modules/@blueprintjs/core/lib/esnext/components/forms/numericInput.js 54:58
Module parse failed: Unexpected token (54:58)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|             shouldSelectAfterUpdate: false,
|             stepMaxPrecision: NumericInput_1.getStepMaxPrecision(this.props),
>             value: getValueOrEmptyValue(this.props.value ?? this.props.defaultValue),
|         };
|         // updating these flags need not trigger re-renders, so don't include them in this.state.
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/index.js 38:0-37 38:0-37
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysDialog.js
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysEvents.js
 @ ./node_modules/@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysTarget.js
 @ ./src/withEditorInteractions/createSequenceInputPopup.js
 @ ./src/withEditorInteractions/index.js
 @ ./src/index.js
 @ ./demo/src/index.js
 @ multi ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ReactRefreshEntry.js (webpack)-dev-server/client?http://localhost:3344/ ./node_modules/@pmmmwh/react-refresh-webpack-plugin/src/runtime/ErrorOverlayEntry.js (webpack)/hot/only-dev-server.js ./demo/src/index.js

I got similar looking webpack errors when trying the “mainFields” solution.

I started suddenly to have the same problem. The strange thing is that I cannot reproduce it when I build the application (CRA + typescript) myself, but the CI build has the issue. I tried several versions of typescript / blueprint / react (I first thought that bumping to the latest version caused the problem but it didn’t).

Maybe this has to do with node version. I’m using 13.7.0 locally (no issue) but CI uses older versions (one env uses 8.x, the other I’m not sure).

Edit: I applied the same workaround as in commit just above and it did the trick 👍

This was fixed by https://github.com/palantir/blueprint/pull/3230.

Also @alxmiron it can be safe to add esnext to resolve.mainFields even if you support older browsers as long as you are using babel-loader and you are babeling your dependencies. Check out this blog post from the babel folks on their thoughts towards babeling deps.