Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Elements hello world throws error #3225

Closed
owencm opened this issue Oct 1, 2017 · 7 comments
Closed

Custom Elements hello world throws error #3225

owencm opened this issue Oct 1, 2017 · 7 comments

Comments

@owencm
Copy link

owencm commented Oct 1, 2017

Is this a bug report?

Yes

Can you also reproduce the problem with npm 4.x?

Yes

Which terms did you search for in User Guide?

Custom Elements, Web Components. No results.

Environment

  1. node -v: v8.6.0
  2. npm -v: 5.3.0
  3. yarn --version (if you use Yarn): N/A
  4. npm ls react-scripts (if you haven’t ejected): N/A

Then, specify:

  1. Operating system: macOS 10.12.6
  2. Browser and version (if relevant): Chrome Canary 63.0.3223.8 (also fails on Stable)

Steps to Reproduce

  1. Create a file containing the following "hello world" Custom Element:
class HelloWorld extends HTMLElement {
  connectedCallback() {
    this.innerHTML = "Hello world";
  }
}

customElements.define('hello-world', HelloWorld)
  1. import this file (e.g. import './hello-world.js) into any React component and use it: <hello-world />

Expected Behavior

Text "hello world" is rendered on screen.

This correct behavior is observed when using the custom element outside of React (included in repro repo), i.e.:

<!doctype>
<body>
<hello-world />
<script src='hello-world.js'></script>
</body>

Actual Behavior

Text isn't rendered, console error is shown: Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.

Reproducible Demo

Example minimal CRA project: https://github.com/owencm/custom-elements-issue

Running it demonstrates the issue.

@owencm
Copy link
Author

owencm commented Oct 1, 2017

Looking into this, I think it's because we're transpiring ES6 classes by default, but customElements.define only works with ES6 classes.

Not sure of the solution though...

@owencm
Copy link
Author

owencm commented Oct 1, 2017

Rob Dodson talks about this issue in the context of Angular here: https://youtu.be/Ucq9F-7Xp8I?t=7m57s

Sounds like the solution is to use Webpack to bundle in https://github.com/webcomponents/webcomponentsjs/blob/master/custom-elements-es5-adapter.js without transpiling.

@gaearon
Copy link
Contributor

gaearon commented Nov 3, 2017

Yep, this isn't expected to work with Babel.
You will probably get a better answer from the community who use custom elements.

@robdodson
Copy link

FWIW, using this babel plugin https://github.com/github/babel-plugin-transform-custom-element-classes seems to fix the issue. The problem is Babel can't properly extend built-ins like HTMLElement, Array, etc.

@robdodson
Copy link

Looping back around to this issue. If anyone runs across it, you can fix the error by including the custom-elements-es5-adapter.js detailed here: https://reactjs.org/docs/web-components.html#using-react-in-your-web-components

@dzole0311
Copy link

Looping back around to this issue. If anyone runs across it, you can fix the error by including the custom-elements-es5-adapter.js detailed here: https://reactjs.org/docs/web-components.html#using-react-in-your-web-components

This solved my issue with Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function. In my case I was accidentally transpiling 'custom-elements-es5-adapter.js' with gulp.

@oswee
Copy link

oswee commented Dec 5, 2018

Using Webpack there. Tnx to @robdodson avice added those 2 plugins:

        rules: [
            {
                test: /\.js$/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: ['es2015'],
                            plugins: ['transform-custom-element-classes', 'transform-es2015-classes']
                        },
                    }
                ],
            },
            {
                test: /\.scss$/,
                use: extractPlugin.extract({
                    use: ['css-loader', 'sass-loader']
                }),
            },
        ]
    },

to my webpack.config.js. Works like a charm.

@lock lock bot locked and limited conversation to collaborators Jan 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants