TypeError: Cannot call a class as a function in stenciljs

Viewed 571

I trying to use multiselect-react-dropdown package inside my stencil project, but while rendering I'm getting this error, I found many solution for react but nothing really worked, Can anyone help do same in stenciljs.

import { Component, h, State } from '@stencil/core';
import { Multiselect } from 'multiselect-react-dropdown';


@Component({
    tag: 'ui-card',
    styleUrl: 'style.scss',
    shadow: true
})

export class UiCard {
    @State() state: any;

    constructor() {
        this.state = {
            options: [{ name: 'Srigar', id: 1 }, { name: 'Sam', id: 2 }]
        };
    }

    onSelect(selectedList, selectedItem) {
        console.log(selectedItem)
        console.log(selectedList)
    }

    onRemove(selectedList, removedItem) {
        console.log(selectedList)
        console.log(removedItem)
    }
    render() {
        return (<div>
            <Multiselect
                options={this.state.options}
                selectedValues={this.state.selectedValue}
                onSelect={this.onSelect}
                onRemove={this.onRemove}
            />
        </div>)
    }
}
2 Answers

StencilJS is not related to React.
Indeed they both are using JSX/TSX as a markup language, but React uses it's own React implementation of it, while StencilJS uses h jsxFactory.
As you may know, JSX is transpired to the regular function calls like createElement which return a Virtual DOM object to render.
So, to render react Virtual DOM object to the page you need to call ReactDOM.render(), meanwhile Stencil compiles it to the web-components.
Despite a lot of common things like JSX, props/state and other - React and StencilJS are completely different tools.

You can use <slot> as a workaround, but I think there might be some performance issues.

Though I wouldn't recommend it, it's possible to use react components inside Stencil, by including the react runtime in your component (yeah sounds pretty ineffective).

See my answer here: https://stackoverflow.com/a/62046928/2897426. It's for using a react-bootstrap component which is fairly similar. Note that Stencil's JSX (or really TSX) is not compatible with React's JSX, thus you can't use JSX to pass the properties. It'll be something like

import { Component, h, State } from '@stencil/core';
import { Multiselect } from 'multiselect-react-dropdown';
import ReactDOM from 'react-dom';
import React from 'react';

@Component({
    tag: 'ui-card',
    styleUrl: 'style.scss',
    shadow: true
})
export class UiCard {
  @Element() host: HTMLUiCardElement;

  @State() state: any;

  @Watch('state')
  onStateChange() {
    const props = {
      options: this.state.options,
      // ...
    };

    ReactDOM.render(React.createElement(Multiselect, props), this.host);
  }

  componentWillLoad() {
    this.onStateChange();
  }

  render() {
    return <Host />;
  }
}

Again, I don't recommend doing this, it'll completely bloat your component with the whole react runtime. Just saying it's possible.

Related