preact
preact copied to clipboard
Support for handleEvent DOM interface
Reproduction
class Foo {
click(e) {
this.setState({ clicked: true })
}
handleEvent(e) {
// nicety: `this` is the component
this[e.type](e)
}
render() {
return <button onClick={this} />
}
}
Steps to reproduce
Click the button.
Expected Behavior
handleEvent is used and doesn't throw an error.
Actual Behavior
this.l[e.type](P.event ? P.event(e) : e) throws an error, as this.l[e.type] is this.
That's interesting! First time I've heard of it. If you can't wait, you can patch that into Preact via an option hook:
import { options } from "preact";
let oldVNode = options.vnode;
options.vnode = vnode => {
const { type, props } = vnode;
// Only check DOM nodes
if (typeof type === "string") {
for (const name in props) {
const value = props[name];
if (value && typeof value.handleEvent === "function") {
props[name] = value.handleEvent;
}
}
}
if (oldVNode) oldVNode(vnode);
};
Thank you for the quick reply!
One note, wouldn't it be easier to check if the given event handler is this and then call it accordingly? Sadly, I don't understand Preact enough to help fix this - if you tell me how exactly are events added, or where, I could make prepare a PR.
Apart from that, I here is some imaginary code:
"before":
addEventListener(eventName, preactEventRouter, {opts})
"after":
addEventListener(eventName, eventFn === this ? this : preactEventRouter, {opts})
I hope this shows my point.
(More about this here: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38)
The trick here is that we currently use a "proxy" handle in order to avoid constantly removing and re-adding handlers when developers use inline functions in render methods. If we reimplement support for handleEvent on top of function listeners, it loses all of the performance advantages.
But! I think there might be a way for us to switch to internally using handleEvent...
Sounds reasonable and the but sounds interesting. Any help needed in exploring?
Definitely! I can throw a PR together that should at least show the rough outline of what we are proposing here, then we can go from there?
Sure, let's do this :)
Just an update since I stumbled on this in my neverending list of tasks: I did get a chance to prototype full support for object event listener values in Preact, it just ends up being a size increase we'll need to find workarounds for:
https://gist.github.com/developit/bd824b90cd4c26db0d99576bd4737273
Just for Reference:
February 2020 Andrea Giammarchi @WebReflection posted a workaround for using EventListener.handleEvent in React.