Nx, React, Lit and Storybook: Class constructor `LitElement` cannot be invoked without `new`
See original GitHub issueCurrent Behavior
Hey there Nx devs. I’m new to Nx but loving it so far. When I try to use Lit with the React stack, however, I’m unclear about how to properly configure Nx/Babel/Webpack to work with Lit and Storybook.
This actually may be something simple in Babel or Webpack, based on some prior related issues, all of which point to es5
/ other transpilation settings. However, being new to Nx, I’m unable to reconcile these hints with what I should do in .storybook
to get things to interoperate correctly. Any help would be deeply appreciated as Nx looks awesome and we’d love to adopt.
Expected Behavior
Through the @lit-labs/react
adapter, I should theoretically be able to define a Lit component, wrap it in a React component, and then display it in Storybook as a React component
Steps to Reproduce
Please find a Github repo here reproducing these steps
- Execute
npx create-nx-workspace@latest --preset=react --packageManager=yarn
- Provide answers (in my case, I provided below values)
- Workspace name:
test
- Application name:
test
- Default stylesheet format:
styled-components
- Use Nx Cloud?
no
- Jump in and run a quick build
cd test && nx build
- Add Storybook (directions here)
yarn add --dev @nrwl/storybook
nx g @nrwl/react:storybook-configuration test
, provide answers- Config cypress e2e…
true
- Automatically generate *.stories.ts…
true
- Automatically generate *.spec.ts…
true
- Config cypress e2e…
- Run Storybook to make sure it works with
nx run test:storybook
. All should be fine. - Define a Lit component, like so:
yarn add lit
- Add code below
import * as React from 'react';
import { LitElement, html, TemplateResult } from 'lit';
import { customElement } from 'lit/decorators/custom-element.js';
import {createComponent} from '@lit-labs/react';
@customElement("test-element")
export class TestElement extends LitElement {
override render(): TemplateResult {
return html`<b>hello lit</b>`;
}
}
export const MyElementComponent = createComponent(
React,
'test-element',
TestElement,
{
onactivate: 'activate',
onchange: 'change',
}
);
- Run the build and Storybook and all still works.
- Now, clone the sample story and tweak it to show the component:
import { Story, Meta } from '@storybook/react';
import { MyElementComponent } from './test';
export default {
component: MyElementComponent,
title: 'My Element',
} as Meta;
const Template: Story = (args) => <MyElementComponent {...args} />;
export const Primary = Template.bind({});
Primary.args = {};
- Run Storybook again. Observe in the console that it fails with:
test.ts:8 Uncaught TypeError: Class constructor LitElement cannot be invoked without 'new'
at new TestElement (main.iframe.bundle.js:1120:24)
(... full stacktrace provided below...)
Failure Logs
test.ts:8 Uncaught TypeError: Class constructor LitElement cannot be invoked without 'new'
at new TestElement (main.iframe.bundle.js:1120:24)
at createElement (vendors-node_modules_babel_runtime_helpers_inheritsLoose_js-node_modules_babel_runtime_helper-69b7d5.iframe.bundle.js:69152:34)
at createInstance (vendors-node_modules_babel_runtime_helpers_inheritsLoose_js-node_modules_babel_runtime_helper-69b7d5.iframe.bundle.js:70349:20)
at completeWork (vendors-node_modules_babel_runtime_helpers_inheritsLoose_js-node_modules_babel_runtime_helper-69b7d5.iframe.bundle.js:79621:28)
at completeUnitOfWork (vendors-node_modules_babel_runtime_helpers_inheritsLoose_js-node_modules_babel_runtime_helper-69b7d5.iframe.bundle.js:82964:16)
at performUnitOfWork (vendors-node_modules_babel_runtime_helpers_inheritsLoose_js-node_modules_babel_runtime_helper-69b7d5.iframe.bundle.js:82939:5)
at workLoopSync (vendors-node_modules_babel_runtime_helpers_inheritsLoose_js-node_modules_babel_runtime_helper-69b7d5.iframe.bundle.js:82859:5)
at renderRootSync (vendors-node_modules_babel_runtime_helpers_inheritsLoose_js-node_modules_babel_runtime_helper-69b7d5.iframe.bundle.js:82822:7)
at performSyncWorkOnRoot (vendors-node_modules_babel_runtime_helpers_inheritsLoose_js-node_modules_babel_runtime_helper-69b7d5.iframe.bundle.js:82445:18)
at scheduleUpdateOnFiber (vendors-node_modules_babel_runtime_helpers_inheritsLoose_js-node_modules_babel_runtime_helper-69b7d5.iframe.bundle.js:82033:7)
Environment
➜ test git:(main) ✗ nx report
> NX Report complete - copy this into the issue template
Node : 16.14.0
OS : darwin arm64
yarn : 1.22.17
nx : 13.9.4
@nrwl/angular : undefined
@nrwl/cypress : 13.9.4
@nrwl/detox : undefined
@nrwl/devkit : 13.9.4
@nrwl/eslint-plugin-nx : 13.9.4
@nrwl/express : undefined
@nrwl/jest : 13.9.4
@nrwl/js : 13.9.4
@nrwl/linter : 13.9.4
@nrwl/nest : undefined
@nrwl/next : undefined
@nrwl/node : undefined
@nrwl/nx-cloud : undefined
@nrwl/nx-plugin : undefined
@nrwl/react : 13.9.4
@nrwl/react-native : undefined
@nrwl/schematics : undefined
@nrwl/storybook : 13.9.4
@nrwl/web : 13.9.4
@nrwl/workspace : 13.9.4
typescript : 4.5.5
rxjs : 6.6.7
---------------------------------------
Community plugins:
Issue Analytics
- State:
- Created a year ago
- Comments:8 (2 by maintainers)
I was facing the same problem, but with a simple web (js based) app. To fix, I used the “swc” compiler for building, and created a .swcrc file in my app (apps/my-app) directory. I then copied the default json (https://swc.rs/docs/configuration/swcrc) into this file and updated the target to es2017 (I also had to remove the comment).
This usually means that a subclass of LitElement has been compiled to no longer be a real class (ie, compiled to an “ES5 class”) and is invoking the LitElement constructor like
LitElement.call(this)
. That doesn’t work with real classes.The solution is to either compile all of your libraries to ES5 (and use the custom elements es5 adapter), or none of them. Unless you’re supporting IE11 there’s really no reason to compile to ES5 anymore.