Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import client-side HTML into Gatsby/React?

I’m a react noob and self-taught, so I’m sure I am doing something stupid. I’m trying to make a small bit of client-side rendered html into a component within my Gatsby site. Been battling this for 4 days. I'm desperate to get this Vue component into my Gatsby site.

Here's the code for my component:

import React, { Component } from "react"
import { Helmet } from "react-helmet"
import DemoHTML from '../../static/demo.html');


class Model extends Component {
  componentDidMount() {

    // set up and use external package as needed

    const Mount = React.createClass({
        render: function(){
          return (
            <section contentEditable='false' dangerouslySetInnerHTML={{ __html: DemoHTML }} />
          );
        }
      });
  }
  render(props, Mount) {
    return (
      <React.Fragment>

<Helmet>

<script type="text/javascript" src="https://unpkg.com/vue"></script>
<script type="text/javascript" src="https://unpkg.com/zircle"></script></Helmet>
<Mount></Mount>
      </React.Fragment>
    )
  }
}


export default Model;


Then, here is the HTML that is imported:



                    

<div id="app">
  <z-canvas :views='$options.components'>
  </z-canvas>
</div>

    <script>

const one = [
    template: `
    <z-view style="border-color: #8F6AFA; font-family: 'Montserrat', sans-serif; font-weight: bold; color: #ffffff; border-width: 1px; background-image: linear-gradient(90deg, #292929 2.11%, #000000 104.85%)" />
` ]
<!---  truncated tested working content for readability  -->


  

    new Vue({
      el: 'app',
      components: {
        one
      },
      mounted () {
        this.$zircle.setView('one')
      }

    })
</script>

Lastly, here's my errors in console and on page...

On page error:


Unhandled Runtime Error
Close
One unhandled runtime error found in your files. See the list below to fix it:


Error in function createFiberFromTypeAndProps in ./node_modules/react-dom/cjs/react-dom.development.js:25058
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. Check the render method of `Model`.

./node_modules/react-dom/cjs/react-dom.development.js:25058
Open in Editor
  25056 |           {
  25057 |             {
> 25058 |               throw Error( "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " + (type == null ? type : typeof type) + "." + info );
  25059 |             }
  25060 |           }


It's helpful to note that the HTML page does render perfectly on its own.

Thank you!

Updated console



DevTools failed to load source map: Could not load content for chrome-extension://fddhonoimfhgiopglkiokmofecgdiedb/MeetingScheduleResource.js.map: HTTP error: status code 404, net::ERR_UNKNOWN_URL_SCHEME
vue:9108 You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
vue:634 [Vue warn]: Cannot find element: #app
warn @ vue:634
query @ vue:5710
Vue.$mount @ vue:11931
Vue._init @ vue:5026
Vue @ vue:5092
(anonymous) @ test.js:4
client.js:95 [HMR] connected
client.js:195 [HMR] bundle has 1 warnings
client.js:196 Critical dependency: the request of a dependency is an expression
react.development.js:220 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check your code at model.js:27.
    at Model (webpack-internal:///./src/pages/model.js:21:23)
    at PageRenderer (webpack-internal:///./.cache/page-renderer.js:23:29)
    at PageQueryStore (webpack-internal:///./.cache/query-result-store.js:41:30)
    at RouteHandler
    at div
    at FocusHandlerImpl (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:359:5)
    at FocusHandler (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:330:19)
    at RouterImpl (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:235:5)
    at Location (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:64:23)
    at Router
    at ScrollHandler (webpack-internal:///./node_modules/gatsby-react-router-scroll/scroll-handler.js:36:35)
    at RouteUpdates (webpack-internal:///./.cache/navigation.js:285:32)
    at EnsureResources (webpack-internal:///./.cache/ensure-resources.js:22:30)
    at LocationHandler (webpack-internal:///./.cache/root.js:69:29)
    at LocationProvider (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:84:5)
    at Location (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:64:23)
    at Root
    at pe (webpack-internal:///./node_modules/gatsby-plugin-image/dist/index.browser-8ac214e0.js:889:13)
    at StaticQueryStore (webpack-internal:///./.cache/query-result-store.js:131:32)
    at ErrorBoundary (webpack-internal:///./.cache/fast-refresh-overlay/components/error-boundary.js:24:35)
    at DevOverlay (webpack-internal:///./.cache/fast-refresh-overlay/index.js:114:23)
    at RootWrappedWithOverlayAndProvider
    at App (webpack-internal:///./.cache/app.js:205:68)
printWarning @ react.development.js:220
error @ react.development.js:196
createElementWithValidation @ react.development.js:2215
render @ model.js:26
finishClassComponent @ react-dom.development.js:17485
updateClassComponent @ react-dom.development.js:17435
beginWork @ react-dom.development.js:19073
beginWork$1 @ react-dom.development.js:23940
performUnitOfWork @ react-dom.development.js:22776
workLoopSync @ react-dom.development.js:22707
renderRootSync @ react-dom.development.js:22670
performSyncWorkOnRoot @ react-dom.development.js:22293
scheduleUpdateOnFiber @ react-dom.development.js:21881
updateContainer @ react-dom.development.js:25482
eval @ react-dom.development.js:26021
unbatchedUpdates @ react-dom.development.js:22431
legacyRenderSubtreeIntoContainer @ react-dom.development.js:26020
render @ react-dom.development.js:26103
runRender @ app.js:230
eval @ app.js:242
setTimeout (async)
eval @ app.js:241
Promise.then (async)
eval @ app.js:171
Promise.then (async)
eval @ app.js:51
./.cache/app.js @ commons.js:1663
options.factory @ commons.js:4121
__webpack_require__ @ commons.js:3478
(anonymous) @ commons.js:4831
__webpack_require__.O @ commons.js:3527
(anonymous) @ commons.js:4832
(anonymous) @ commons.js:4834
react.development.js:220 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check your code at model.js:27.
    at Model (webpack-internal:///./src/pages/model.js:21:23)
    at PageRenderer (webpack-internal:///./.cache/page-renderer.js:23:29)
    at PageQueryStore (webpack-internal:///./.cache/query-result-store.js:41:30)
    at RouteHandler
    at div
    at FocusHandlerImpl (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:359:5)
    at FocusHandler (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:330:19)
    at RouterImpl (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:235:5)
    at Location (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:64:23)
    at Router
    at ScrollHandler (webpack-internal:///./node_modules/gatsby-react-router-scroll/scroll-handler.js:36:35)
    at RouteUpdates (webpack-internal:///./.cache/navigation.js:285:32)
    at EnsureResources (webpack-internal:///./.cache/ensure-resources.js:22:30)
    at LocationHandler (webpack-internal:///./.cache/root.js:69:29)
    at LocationProvider (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:84:5)
    at Location (webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:64:23)
    at Root
    at pe (webpack-internal:///./node_modules/gatsby-plugin-image/dist/index.browser-8ac214e0.js:889:13)
    at StaticQueryStore (webpack-internal:///./.cache/query-result-store.js:131:32)
    at ErrorBoundary (webpack-internal:///./.cache/fast-refresh-overlay/components/error-boundary.js:24:35)
    at DevOverlay (webpack-internal:///./.cache/fast-refresh-overlay/index.js:114:23)
    at RootWrappedWithOverlayAndProvider
    at App (webpack-internal:///./.cache/app.js:205:68)
printWarning @ react.development.js:220
error @ react.development.js:196
createElementWithValidation @ react.development.js:2215
render @ model.js:26
finishClassComponent @ react-dom.development.js:17485
updateClassComponent @ react-dom.development.js:17435
beginWork @ react-dom.development.js:19073
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
beginWork$1 @ react-dom.development.js:23964
performUnitOfWork @ react-dom.development.js:22776
workLoopSync @ react-dom.development.js:22707
renderRootSync @ react-dom.development.js:22670
performSyncWorkOnRoot @ react-dom.development.js:22293
scheduleUpdateOnFiber @ react-dom.development.js:21881
updateContainer @ react-dom.development.js:25482
eval @ react-dom.development.js:26021
unbatchedUpdates @ react-dom.development.js:22431
legacyRenderSubtreeIntoContainer @ react-dom.development.js:26020
render @ react-dom.development.js:26103
runRender @ app.js:230
eval @ app.js:242
setTimeout (async)
eval @ app.js:241
Promise.then (async)
eval @ app.js:171
Promise.then (async)
eval @ app.js:51
./.cache/app.js @ commons.js:1663
options.factory @ commons.js:4121
__webpack_require__ @ commons.js:3478
(anonymous) @ commons.js:4831
__webpack_require__.O @ commons.js:3527
(anonymous) @ commons.js:4832
(anonymous) @ commons.js:4834
react-dom.development.js:25058 Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `Model`.
    at createFiberFromTypeAndProps (react-dom.development.js:25058)
    at createFiberFromElement (react-dom.development.js:25086)
    at createChild (react-dom.development.js:13446)
    at reconcileChildrenArray (react-dom.development.js:13719)
    at reconcileChildFibers (react-dom.development.js:14125)
    at reconcileChildren (react-dom.development.js:16990)
    at finishClassComponent (react-dom.development.js:17511)
    at updateClassComponent (react-dom.development.js:17435)
    at beginWork (react-dom.development.js:19073)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
createFiberFromTypeAndProps @ react-dom.development.js:25058
createFiberFromElement @ react-dom.development.js:25086
createChild @ react-dom.development.js:13446
reconcileChildrenArray @ react-dom.development.js:13719
reconcileChildFibers @ react-dom.development.js:14125
reconcileChildren @ react-dom.development.js:16990
finishClassComponent @ react-dom.development.js:17511
updateClassComponent @ react-dom.development.js:17435
beginWork @ react-dom.development.js:19073
callCallback @ react-dom.development.js:3945
invokeGuardedCallbackDev @ react-dom.development.js:3994
invokeGuardedCallback @ react-dom.development.js:4056
beginWork$1 @ react-dom.development.js:23964
performUnitOfWork @ react-dom.development.js:22776
workLoopSync @ react-dom.development.js:22707
renderRootSync @ react-dom.development.js:22670
performSyncWorkOnRoot @ react-dom.development.js:22293
scheduleUpdateOnFiber @ react-dom.development.js:21881
updateContainer @ react-dom.development.js:25482
eval @ react-dom.development.js:26021
unbatchedUpdates @ react-dom.development.js:22431
legacyRenderSubtreeIntoContainer @ react-dom.development.js:26020
render @ react-dom.development.js:26103
runRender @ app.js:230
eval @ app.js:242
setTimeout (async)
eval @ app.js:241
Promise.then (async)
eval @ app.js:171
Promise.then (async)
eval @ app.js:51
./.cache/app.js @ commons.js:1663
options.factory @ commons.js:4121
__webpack_require__ @ commons.js:3478
(anonymous) @ commons.js:4831
__webpack_require__.O @ commons.js:3527
(anonymous) @ commons.js:4832
(anonymous) @ commons.js:4834

UPDATE

I have made the suggested update to ESM (and also updated in the question. One thing I wanted to share with you all, in case it warrants consideration. The reason this script must be rendered on client side is it is a vue library. (See Zircle.github.io)

If everything is loaded client side, I don't see why this would be an issue. But, just an FYI.

like image 636
NIcole is the worst Avatar asked Jul 09 '21 22:07

NIcole is the worst


2 Answers

First step to getting this to work is to add support for HTML modules. Gatsby doesn't recognize them out-of-the-box.

Install html-loader using:

$ npm i -D html-loader

In gatsby-node.js

exports.onCreateWebpackConfig = ({
  actions,
}) => {
  actions.setWebpackConfig({
    module: {
      rules: [
        {
          test: /\.html$/,
          loader: require.resolve('html-loader'),
          options: {
            minimize: false,
          },
        },
      ],
    },
  })
}

Also make sure you don't fix ESM imports and commonjs require(). Stick to static ESM imports/exports. So as already suggested remove the require() call and use imports for getting the HTML contents of ../../static/demo.html.

import DemoHtml from '../../static/demo.html';

Can't foresee what other problems you might get into but try the above and report back.

like image 182
Z. Zlatev Avatar answered Oct 12 '22 06:10

Z. Zlatev


Got zircle integrated into React/Gatsby.

The useScript hook is necessary wait till the vue and then zircle library is fully loaded.

Install package dangerously-set-html-content - as you need Javascript inside HTML to be executed.

I used useScript code from https://usehooks.com/useScript/

import React, { Component } from "react";
import DemoHTML from "../../static/zircle.html";

import InnerHTML from "dangerously-set-html-content";
import "zircle/dist/zircle.css";
import useScript from "../hooks/useScript";

export default function LoadVue() {
  const status = useScript("https://unpkg.com/vue");
  return <>{status === "ready" && <Zircle />}</>;
}

function Zircle() {
  const status = useScript("https://unpkg.com/zircle");
  return <>{status === "ready" && <InnerHTML html={DemoHTML} />}</>;
}

and the zircle.html is

     <div> Hello Zircle</div>
<div id="app2">
  <z-canvas :views="$options.components"></z-canvas>
</div>

<script>
  const home = {
    template: `<z-view>Hello World!</z-view>`
  }
  new Vue({
    el: '#app2',
    components: {
      home
    },
    mounted () {
      this.$zircle.setView('home')
    }
  })
</script>
like image 29
Meera Datey Avatar answered Oct 12 '22 06:10

Meera Datey