developit / htm

Hyperscript Tagged Markup: JSX alternative using standard tagged templates, with compiler support.
Apache License 2.0
8.64k stars 169 forks source link

Difficulty combining htm with preact and material ui #243

Closed schlichtanders closed 1 year ago

schlichtanders commented 1 year ago

Hi there, I am using preact and htm already and would like to add material ui

here a minimal example

import {render, h} from "https://esm.sh/v66/preact@10.6.6?target=es2020"
import htm from "https://esm.sh/v66/htm@3.1.0?target=es2020"
const html = htm.bind(h)

import Button from "https://esm.sh/v66/@mui/material@5.11.15/Button?target=es2020"

render(html`<${Button} variant="contained">Hello World</Button>`, document.body)

this produces the following error

create-context.js:3 Uncaught TypeError: Cannot read properties of undefined (reading '__k')
    at oe (create-context.js:3:16)
    at index.js:8:1

when using Button somewhere deeper inside nested html preact components, I get the following error

Uncaught DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('[object Object]') is not a valid name.
    at ne (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:6758)
    at M (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:6149)
    at z (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:2118)
    at ne (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:7190)
    at M (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:6149)
    at z (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:2118)
    at ne (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:7190)
    at M (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:6149)
    at z (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:2118)
    at ne (https://esm.sh/stable/preact@10.6.6/es2020/preact.mjs:2:7190)
schlichtanders commented 1 year ago

I was able to prevent the error by aliasing dependencies like

import Button from "https://esm.sh/v66/@mui/material@5.11.15/Button?alias=react:preact/compat,react-dom:preact/compat&deps=preact@10.6.6&target=es2020"

however now nothing appears. It seems like the button is entirely ignored

schlichtanders commented 1 year ago

Finally got it working, apparently a third alias was needed: react/jsx-runtime:preact/jsx-runtime

my final version (moving to stable instead of fixed version v66 because internally esm still refers to stable links)

import {render, h} from "https://esm.sh/stable/preact@10.6.6?target=es2020"
import htm from "https://esm.sh/stable/htm@3.1.0?target=es2020"
const html = htm.bind(h)

import Button from "https://esm.sh/stable/@mui/material@5.11.15/Button?alias=react:preact/compat,react-dom:preact/compat,react/jsx-runtime:preact/jsx-runtime&deps=preact@10.6.6&target=es2020"

render(html`<${Button} variant="contained">Hello World</Button>`, document.body)

After understanding more the issues behind my problem, I guess preact would have been a better place to raise this issue. Still learning.

HarikrishnanBalagopal commented 1 month ago

Finally got it working, apparently a third alias was needed: react/jsx-runtime:preact/jsx-runtime

my final version (moving to stable instead of fixed version v66 because internally esm still refers to stable links)

import {render, h} from "https://esm.sh/stable/preact@10.6.6?target=es2020"
import htm from "https://esm.sh/stable/htm@3.1.0?target=es2020"
const html = htm.bind(h)

import Button from "https://esm.sh/stable/@mui/material@5.11.15/Button?alias=react:preact/compat,react-dom:preact/compat,react/jsx-runtime:preact/jsx-runtime&deps=preact@10.6.6&target=es2020"

render(html`<${Button} variant="contained">Hello World</Button>`, document.body)

After understanding more the issues behind my problem, I guess preact would have been a better place to raise this issue. Still learning.

@schlichtanders This fix doesn't seem to be working anymore?

https://jsfiddle.net/1trL7z8f/

"Uncaught TypeError: Cannot read properties of undefined (reading 'context')"

The full error

Uncaught TypeError: Cannot read properties of undefined (reading 'context')
    at Module.M (index.js:344:36)
    at ss (useThemeWithoutDefault.js:9:30)
    at ps (useTheme.js:7:10)
    at Q (useThemeProps.js:11:15)
    at q (useThemeProps.js:7:10)
    at Button.js:221:17
    at E.t [as constructor] (forwardRef.js:34:10)
    at E._e [as render] (index.js:518:14)
    at M (index.js:181:12)
    at z (children.js:137:3)
ethicalads.min.js:1 Un
rschristian commented 1 month ago

I'd suggest using import maps, here's a working example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <script type="importmap">
      {
        "imports": {
          "preact": "https://esm.sh/preact@10.19.2",
          "preact/": "https://esm.sh/preact@10.19.2/",
          "htm/preact": "https://esm.sh/htm@3.1.1/preact?external=preact",
          "@mui/material/Button": "https://esm.sh/@mui/material@5.15.20/Button?alias=react:preact/compat,react-dom:preact/compat&external=preact"
        }
      }
    </script>
  </head>
  <body>
    <div id="app"></div>

    <script type="module">
      import { render } from 'preact';
      import { html } from 'htm/preact';

      import Button from '@mui/material/Button';

      render(
        html`<${Button} variant="contained">Hello World</Button>`,
        document.getElementById('app')
      );
    </script>
  </body>
</html>
HarikrishnanBalagopal commented 1 month ago

I'd suggest using import maps, here's a working example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <script type="importmap">
      {
        "imports": {
          "preact": "https://esm.sh/preact@10.19.2",
          "preact/": "https://esm.sh/preact@10.19.2/",
          "htm/preact": "https://esm.sh/htm@3.1.1/preact?external=preact",
          "@mui/material/Button": "https://esm.sh/@mui/material@5.15.20/Button?alias=react:preact/compat,react-dom:preact/compat&external=preact"
        }
      }
    </script>
  </head>
  <body>
    <div id="app"></div>

    <script type="module">
      import { render } from 'preact';
      import { html } from 'htm/preact';

      import Button from '@mui/material/Button';

      render(
        html`<${Button} variant="contained">Hello World</Button>`,
        document.getElementById('app')
      );
    </script>
  </body>
</html>

That works, Thanks!