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

Using a WebComponent/customElement with React #8249

Closed
burtonsamograd-adsk opened this issue Nov 9, 2016 · 9 comments
Closed

Using a WebComponent/customElement with React #8249

burtonsamograd-adsk opened this issue Nov 9, 2016 · 9 comments

Comments

@burtonsamograd-adsk
Copy link

burtonsamograd-adsk commented Nov 9, 2016

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

class OrionNotificationElement extends HTMLElement {
  constructor () {
    super();

    console.log('OrionNotification');
  }
}

window.customElements.define('orion-notification', OrionNotificationElement);

export default OrionNotificationElement;

import React, { Component } from 'react';
import { default as OrionNotificationElement } from './webcomponents/orion-notification';

class OrionNotification extends Component {
render () {
  return <orion-notification/>;
}
}

Using the component causes the following error:

ReactDOMComponent.js:512 Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.(…)

Pasting the customElement definition into the console and calling document.createElement('orion-notification') creates an element. After loading react, it seems this error occurs.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/reactjs/69z2wepo/).

What is the expected behavior?

I should be able to instantiate the web component.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

Current react and current chrome.

@burtonsamograd-adsk
Copy link
Author

I followed the examples pointed to from this page:

https://facebook.github.io/react/docs/web-components.html

Does anyone know if this page is up to date or accurate?

@gaearon
Copy link
Collaborator

gaearon commented Nov 10, 2016

This is not an issue with React. It appears that the problem is with how Babel transpiles super().

Have you tried not using ES6 classes for this, just like the example you linked to does?

For example, notice no extends or super here:

      // Define WebComponent
      var proto = Object.create(HTMLElement.prototype, {
        attachedCallback: {
          value: function() {
            var mountPoint = document.createElement('span');
            this.createShadowRoot().appendChild(mountPoint);

            var name = this.getAttribute('name');
            var url = 'https://www.google.com/search?q=' + encodeURIComponent(name);
            ReactDOM.render(<a href={url}>{name}</a>, mountPoint);
          }
        }
      });
      document.registerElement('x-search', {prototype: proto});

I’m closing because it is not actionable for React team. You might want to report this to Babel.

@gaearon gaearon closed this as completed Nov 10, 2016
@Jessidhia
Copy link
Contributor

Babel's class transform does not support extending native types: https://babeljs.io/docs/usage/caveats/#classes

@burtonsamograd-adsk
Copy link
Author

burtonsamograd-adsk commented Nov 10, 2016

I was also following the examples from https://developers.google.com/web/fundamentals/getting-started/primers/customelements. This was where I was using the syntax for extending the native types; maybe I need a newer version of babel?

For example, here's a snippet from the article:

class AppDrawer extends HTMLElement {...}
window.customElements.define('app-drawer', AppDrawer);

@gaearon
Copy link
Collaborator

gaearon commented Nov 10, 2016

@burtonsamograd-adsk

As @Kovensky wrote just above, Babel class transform just doesn't support extending built-ins such as HTMLElement. You should either disable class transform (and thus give up older browsers) or use Object.create() as shown above.

@rektide
Copy link

rektide commented Dec 30, 2016

Object.create() is no longer a valid way to create a WebComponent. I opened #8656 to track this (rather than cram that spec behavior change in here).

@parisk
Copy link

parisk commented Oct 28, 2017

Seems like I am bringing something back from the dead 😅.

@gaearon any idea how can I disable class transforming in Babel, when I am using only the react preset?

.babelrc

{
  "presets": ["react"]
}

.package.json (fragment)

  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",

Thanks for your time.

@gaearon
Copy link
Collaborator

gaearon commented Oct 28, 2017

If you only use the React preset Babel won't transform classes. Unless there's some other Babel config (in parent directories or e.g. webpack options).

@palak-temp
Copy link

In my case, it's not related to babel or react. It's caused by chrome extension.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants