ufollettu
ufollettu

Reputation: 882

How to use nested Web Components created by Stenciljs in React

I have a repository with Stencil.js and I create a couple of web components, nested and working in Stencil development environment. in example I have a parent component that use a child component:

import { Component, h, Prop, State } from "@stencil/core";

@Component({
  tag: "parent-component"
})
export class MyParent {

  @Prop() carddata: any;

  render() {
    return (
      <div>
        <child-component
          carddata={this.carddata}
        />
      </div>
    );
  }
}

this is the child component:

import { Component, Prop, h } from "@stencil/core";

@Component({
  tag: "child-component"
})
export class MyChild {

  @Prop() carddata: any;

  renderItems(items: string[]): string {
    let newString = "";
    items.map((item: string) => {
      newString = newString.concat(item, ", ");
    });
    return newString.substr(0, newString.length - 2);
  }

  render() {
    const { items } = JSON.parse(this.carddata);
    return (
      <p>
        Items: <b>{this.renderItems(items)}</b>
      </p>
    );
  }
}

When I build and use the package created in another repository (React app) I have errors on renderig the web components. This is the React Component where I use the web component:

[...]

import * as cardData from "./card-mock-data.json";

[...]

  render() {
    return (
      <Wrap>
        <parent-component
        carddata={JSON.stringify(cardData)}/>
      </Wrap>
    );
  }

[...]

And the error is TypeError: Cannot read property 'map' of undefined. It's hard to debug, because is compiled code, but the error seems to refers to this piece of (compiled) code:

ChildComponent.prototype.renderItems= function (items) {
    var newString = "";
    items.map(function (item) {
        newString = newString.concat(item, ", ");
    });
    return newString.substr(0, newString.length - 2);
};

Maybe I'm wrong with something, Can I pass data to nested component using only the parent tag in React? Maybe I'm missing some "parsing" step?

Thanks for your help

EDIT: add cardData snippet:

{
  "id": "invito-biologia-blu",
  "titolo": "Il nuovo invito alla biologia blu",
  "img": "http://media.curtisinvitoblu.bedita.net/a1/40/curti_a140cb3359b7611d84f80e384d2fb49b/curtis_plus-1A_320x_71bc3567ace1ff728caef1b381d7535b.png",
  "tags": ["Polimeri", "biochimica", "biotecnologie", "sostenibilità"],
  "autori": ["Helena Curtis", "Sue Barnes", "Alicia Mastroianni"],
  "anno": 2017,
  "actions": ["Leggi sul browser", "Sito e risorse del libro", "ZTE"]
}

when I log cardData in render() I have this:

Module {default: {…}, __esModule: true, Symbol(Symbol.toStringTag): "Module"}

Upvotes: 1

Views: 2148

Answers (1)

Michal Cumpl
Michal Cumpl

Reputation: 1037

The problem is, that React 16 passes all data to Custom Elements as HTML attributes. And it just doesn't work for objects or arrays.

More info: https://custom-elements-everywhere.com/libraries/react/results/results.html

The good news is that they may fix this in React 17: https://github.com/facebook/react/issues/11347

To fix this now, you will need to pass the data as properties.

Take a look at the Ionic team solution here: https://github.com/ionic-team/ionic/blob/master/react/src/components/createComponent.tsx

Upvotes: 1

Related Questions