简体   繁体   中英

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?

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 .

You need to bind the current context to the method.

Check Event emit error for more explanation

...
export class Input {
    constructor() {
       this.handleChange = this.handleChange.bind(this);
    }

    @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>
        )
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM