1
votes

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"}
1
What does cardData look like actually if you log in the React portion? - Alexander Staroselsky
@AlexanderStaroselsky It's a JSON file, I'm updated the question with the log too - ufollettu
It doesn’t look like the JSON is importing as you expect. Based on the log it seems to be treating it as a module instead of JSON. This could be an issue with your webpack configuration. The next issue is that I don’t see a property called items in your json. I mention this because in your child stencil component you are attempting to extract a property called items which doesn’t seem to exist, hence the undefined error. Assuming you pass actual JSON data down you probably won’t be destructuring items out, you’d just pass the entire parsed payload to renderItems. - Alexander Staroselsky
You need a specific loader to load json using webpack, but your import could be wrong also in terms of syntax. Just do import cardData from ‘whatever.json’ - Alexander Staroselsky
@AlexanderStaroselsky thank you, I set the import from a ts file and it works - ufollettu

1 Answers

1
votes

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