Hyperapp: Best way to integrate with Material Design Components?

Created on 6 Jan 2018  路  6Comments  路  Source: jorgebucaran/hyperapp

This is probably less of an issue and more of an ask, but I'm trying to integrate with https://github.com/material-components/material-components-web/tree/master/packages/mdc-tabs and running into a console error. My code is here:

https://codepen.io/dizzle/pen/VyrMVe

And for sanity, here's another version without Hyperapp: https://codepen.io/dizzle/pen/xpPPKx

The main thing it's doing is using the element to initialize the Material Design component, as well as using it as a source of local state so that I can reference it later.

element.mdcComponent = new window.mdc.tabs.MDCTabBar(element);

While the codepen works, the console error showing up whenever a tab is clicked is:

Uncaught Error: Invalid tab component given as activeTab: Tab not found within this component's tab list
    at MDCTabBar.setActiveTab_ (VM554 material-components-web.js:2239)
    at HTMLElement.tabSelectedHandler_ (VM554 material-components-web.js:2151)
    at MDCTab.emit (VM554 material-components-web.js:379)
    at Object.notifySelected (VM554 material-components-web.js:2036)
    at HTMLAnchorElement.MDCTabFoundation._this.clickHandler_ (VM554 material-components-web.js:11772)

which makes me think the element for a Tab is changing at some point, although I don't see how because destroy is never being called.

This is a screenshot of the exception being thrown:

2018-01-06 12_04_09-developer tools - https___codepen io_dizzle_pen_vyrmve

And these are some console commands I ran to try to confirm that the activeTab was not contained in the tabs array (even though the innerText matches)

2018-01-06 12_05_34-developer tools - https___codepen io_dizzle_pen_vyrmve

I realize that the MDC library is not something you may have worked with before, but do you happen to have any ideas what might be going on here?

Thanks!

Inquiry

Most helpful comment

I may have found my issue. After debugging, I found that MDCTab constructor was being called twice for each tab. It looks like MDCTabBar automatically calls this for its children. Removing that code seems to have fixed my issue.

All 6 comments

Cross-posted in the material-components-web repo https://github.com/material-components/material-components-web/issues/1889

You might want to take a look at older issue https://github.com/hyperapp/hyperapp/issues/125. Some of the links in it are dead, but the concepts still hold true. If you want to wrap existing components in Hyperapp components, you'll need to understand how to map the lifecycle events (oncreate, onupdate, onremove, ondestroy) in your component wrappers.

Have you considered using Material Design Lite instead? I've used the React-MDL library that manages to wrap those components as functional/stateless.

Edit: apparently MDL is deprecated now, but MDC is still pretty new and seems to rely heavily on mutation. The closest thing I could find to stateless component wrappers is elm-mdc, although it uses MutationObservers and other hacks to fit an imperative square peg into a functional round hole.

@developerdizzle This certainly is not the cause of your problem, but anyhow: I noticed you're passing a key prop to your Tab component function, but then you're not using it in the vnodes returned from that function. You need to:

 return (
    <a
      key={props.key}
      role="tab"
      class="mdc-tab"
      ...

... or the keys won't take effect.

I tried fixing it, and had the same problem, so I don't think that's the end of it. But anyway, if you aren't using keys (or not using them right) you do risk the connection between a component and its element being changed.

@okwolf

You might want to take a look at older issue #125. Some of the links in it are dead, but the concepts still hold true. If you want to wrap existing components in Hyperapp components, you'll need to understand how to map the lifecycle events (oncreate, onupdate, onremove, ondestroy) in your component wrappers.

Thanks very much for the link, I'll take a closer look! I am using the lifecycle events, I believe properly, but maybe not.

Have you considered using Material Design Lite instead

As you noticed, it's been deprecated in favor of MDC. I'll take a look at elm-mdc.

@zaceno

I noticed you're passing a key prop to your Tab component function, but then you're not using it in the vnodes returned from that function.

Just fixed this in the codepen; thank you for pointing it out!

I may have found my issue. After debugging, I found that MDCTab constructor was being called twice for each tab. It looks like MDCTabBar automatically calls this for its children. Removing that code seems to have fixed my issue.

Oh glad you have found a useful way to integrate MDC!

馃帀

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Mytrill picture Mytrill  路  4Comments

VictorWinberg picture VictorWinberg  路  3Comments

zhaotoday picture zhaotoday  路  3Comments

ghost picture ghost  路  3Comments

jamen picture jamen  路  4Comments