Search code examples
reactjsweb-componenteventemitterstenciljs

How to use Stencil's `EventEmitter` inside React JSX?


I created an Input web component with Stencil:

...
export class Input {
    @Prop({ mutable: true }) value: string;
    @Event() changed: EventEmitter<KeyboardEvent>;

    private handleChange (e) {
        this.value = e.target?.value;
        this.changed.emit(e);
    }

    render() {
        return (
            <div class="inputContainer">
                <input  
                    type="text"
                    value={this.value}
                    onInput={this.handleChange}
                />
            </div>
        )
    }
}

Then after trying to use it inside React jsx file, onChanged does not call console.log

...

function App() {
  return (
    <div className="App">
      // does not call console.log
      <ui-input onChanged={(e) => console.log(e)}/>
    </div>
  );
}


As I've read so far it's because React uses the synthetic event instead of Dom events.

Is there any way to use Dom events within JSX element?


Solution

  • You would have to manually attach the event listener using the DOM API, for example:

    document.querySelector('ui-input').addEventListener('changed', console.log)
    

    (You can also use the ref prop to get a reference to the DOM element which is probably more robust.)

    You have another option though, and that's to use the stencil-ds-plugins, specifically the @stencil/react-output-target npm package. When you build your component/library, the output target will generate all the necessary bindings (props, custom events, etc.) for you, and you'll be able to use your component as a react component. The only available docs so far ar in the readme: https://github.com/ionic-team/stencil-ds-plugins#react.