2

I created a web component from VueJs and then compiled it using the command yarn build and then copied the dist folder and pasted it in a ReactJs project. But whenever I tried to import the web component, the ReactJs app breaks and shows an error:

error

I've tried all of the possible ways that I found in the internet but it's not fixing the error.

My VueJs Project Code

AdditionComponent.vue

<template>
  <div>
      <span><strong>Total:</strong> {{ total }}</span>
  </div>
</template>

<script>
export default {
    props: {
        num1: Number,
        num2: Number
    },
    computed: {
        total(){
            return parseInt(this.num1) + parseInt(this.num2);
        }
    }
}
</script>

main.js

import Vue from 'vue'
import wrap from '@vue/web-component-wrapper'

Vue.config.productionTip = false
Vue.config.devtools = false;

const CustomElement = wrap(Vue, () => import('./components/AdditionComponent.vue'));

window.customElements.define('addition-component', CustomElement)

package.json

{
  "name": "app-form",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build  --target wc --inline-vue --name addition-component ./src/main.js",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "vue-template-compiler": "^2.6.11"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

My ReactJs Project Code

App.js

import React, { useState } from 'react';
import logo from './logo.svg';
import './App.css';
import './components/dist/addition-component';


function App() {
  const [ n1, setN1 ] = useState(0);
  const [ n2, setN2 ] = useState(0);

  return (
    <div className="App">
      <input type="number" value={n1} onChange={ e => setN1(e.target.value)}/><br/>
      <input type="number" value={n2} onChange={ e => setN2(e.target.value)}/>
      <addition-component num1={n1} num2={n2} />
    </div>
  );
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

serviceWorker.unregister();

package.json

{
  "name": "app-form-test",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "@webcomponents/webcomponentsjs": "^2.4.4",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-scripts": "3.4.1",
    "vendor-copy": "^2.0.0",
    "vuera": "^0.2.7"
  },
  "scripts": {
    "postinstall": "vendor-copy",
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "presets": [
    "react"
  ],
  "plugins": [
    "vuera/babel"
  ],
  "vendorCopy": [
    {
      "from": "node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js",
      "to": "public/vendor/custom-elements-es5-adapter.js"
    },
    {
      "from": "node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js",
      "to": "public/vendor/webcomponents-bundle.js"
    }
  ]
}

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    
    <div id="root"></div>
  </body>
  <script src="%PUBLIC_URL%/vendor/webcomponents-bundle.js"></script>
  <script>if (!window.customElements) { document.write("<!--"); }</script>
  <script src="%PUBLIC_URL%/vendor/custom-elements-es5-adapter.js"></script>
  <!--! DO NOT REMOVE THIS COMMENT, WE NEED ITS CLOSING MARKER -->
</html>
halfer
  • 19,824
  • 17
  • 99
  • 186

2 Answers2

0

Props in webcomponents cannot contain numbers or uppercase letters. Try changing props name.

teobaj
  • 21
  • 2
-1

React (nearly a decade old now) only for 71% complies with the W3C WebComponents standard.

You have to develop that 29% yourself to make WebComponents work in React

Why: Is it really necessary to make and use new custom elements and web components (HTML tags)?

71% score: Custom Elements eveyrwhere

The advice from the React docs is:

Want to use WebComponents and React? Rewrite the WebComponent to use React syntax...

That is like Tesla saying:

Your battery is empty? Then install an old diesel engine!

That is a like a modern 2020 Front End Developer saying:

You can't select DOM elements? Well, use jQuery then!

Vue, Angular, Svelte, et al, all score 100% on Custom Elements eveyrwhere

Danny '365CSI' Engelman
  • 16,526
  • 2
  • 32
  • 49