Preact: EventSystem

Created on 2 Feb 2016  路  9Comments  路  Source: preactjs/preact

What about SynteticEvents like in React? As I know virtual-dom doesn't have this abstraction

question

Most helpful comment

@savelichalex I didn't meant to imply it would necessarily be worse, just that the gains of using a root listener would be minimal when you already have references to nodes. I'm always up for performance tweaks, but I try to only make adjustments based on facts - data from profiling, benchmarks, etc.

I do somewhat understand your point about touch events, but I don't think this is something that belongs in Preact's _Core_ unless it could be done with _incredibly_ little code/overhead. Allowing Preact to expand constantly over time would render the project meaningless when the overarching goals include being efficient and lightweight. I've been using Preact for both desktop and mobile app development for around half a year now, and have shipped a number of production apps without needing to work around event normalization issues.

Additionally, Preact already has points of extension that would make building a "tap plugin" trivially easy. You could simply inject a vnode hook that transforms events, or even proxies their handlers to normalize event coordinates, names, etc:

import { hooks } from 'preact';

function normalizeTouchEvents({ attributes }) {
    // mutate attributes.onTouchStart or whatever here
}

let compose = (...fns) => r => fns.reduce( (r, f) => f(r), r);

hooks.vnode = compose(hooks.vnode, normalizeTouchEvents);

Lastly, I think you may be attributing far more value and complexity to React's Event System than it actually warrants: all it does is normalize some inconsistencies in older browsers. It does not make touch events work in non-touch browsers, or emulate mouse events in touch environments - it doesn't even account for Pointer Events. In modern browsers, it is very literally a thin abstraction on top of a nearly identical API.

It just wouldn't make sense to bundle this into Preact when the browser support target for the library does not even include the browsers React's own implementation is intended to fix.

I'm going to close this issue for now, but I would be happy to continue discussion on Gitter, opening issues for more specific concerns if they arise.

All 9 comments

Hi @savelichalex - Preact intentionally eschews a synthetic event implementation in order to avoid overhead, both in terms of performance and maintenance. One of the primary goals of the project is to provide a little API surface area as possible, which means relying directly on browser events. If you have a use-case that isn't met by this, please let me know, otherwise I've added this to the "differences" wiki page and we can close the issue.

But this is why i move from virtual-dom to react. This is feature in my opinion has strong influence for performans, at first this is one listener, at second events are taken from pool. And (it maybe more important) SynteticEvents provide crossbrowser API

Preact does provide a cross-browser API, in that it abstracts event handler registration and removal. It proxies events, perhaps mildly similar to React, but does not implement a custom propagation scheme like React does. Are you sure Preact doesn't already meet your needs?

I would need to see some convincing metrics showing root node event observation to be faster than standard addEventListener before venturing down that path.

More importantly, Preact specifically does not attempt to support IE 8 and prior without shims - that means every supported browser for Preact already has addEventListener. For a project where simplicity and size is paramount, I see little reason to cater to less than 1% of browsers at the expense of the other 99%.

Perhaps it would help if we framed the discussion more: what are you doing with events that is not currently supported in Preact?

For example touch events are different in almost browsers, React provide universal api for all events. In additiion most browsers like to add specific fields to events. There are frameworks do universal events, beginning from jQuery, because this is really helphul for developers.

This is question not about my specific action with events, this is about universal api for developers. I think that if you choose library to work with dom, you want to get comfortable and usefull api and not thinking about crossbrowser support. This is should do library for you.

And why think that one root listener isn't better for performance?

@savelichalex I didn't meant to imply it would necessarily be worse, just that the gains of using a root listener would be minimal when you already have references to nodes. I'm always up for performance tweaks, but I try to only make adjustments based on facts - data from profiling, benchmarks, etc.

I do somewhat understand your point about touch events, but I don't think this is something that belongs in Preact's _Core_ unless it could be done with _incredibly_ little code/overhead. Allowing Preact to expand constantly over time would render the project meaningless when the overarching goals include being efficient and lightweight. I've been using Preact for both desktop and mobile app development for around half a year now, and have shipped a number of production apps without needing to work around event normalization issues.

Additionally, Preact already has points of extension that would make building a "tap plugin" trivially easy. You could simply inject a vnode hook that transforms events, or even proxies their handlers to normalize event coordinates, names, etc:

import { hooks } from 'preact';

function normalizeTouchEvents({ attributes }) {
    // mutate attributes.onTouchStart or whatever here
}

let compose = (...fns) => r => fns.reduce( (r, f) => f(r), r);

hooks.vnode = compose(hooks.vnode, normalizeTouchEvents);

Lastly, I think you may be attributing far more value and complexity to React's Event System than it actually warrants: all it does is normalize some inconsistencies in older browsers. It does not make touch events work in non-touch browsers, or emulate mouse events in touch environments - it doesn't even account for Pointer Events. In modern browsers, it is very literally a thin abstraction on top of a nearly identical API.

It just wouldn't make sense to bundle this into Preact when the browser support target for the library does not even include the browsers React's own implementation is intended to fix.

I'm going to close this issue for now, but I would be happy to continue discussion on Gitter, opening issues for more specific concerns if they arise.

Sorry to ask in this old issue... However, I need now to normalize the touch events in my project. The problem is that an external library uses the touch events and with Preact is not working in Iphone / Ipad. I'm using Preact 10.3.4. I tried this:

import { hooks } from 'preact';

function normalizeTouchEvents({ attributes }) {
    // mutate attributes.onTouchStart or whatever here
}

let compose = (...fns) => r => fns.reduce( (r, f) => f(r), r);

hooks.vnode = compose(hooks.vnode, normalizeTouchEvents);

But looks that nowadays hooks doesn't exist. How can I do it now @developit ? Is there an alternative? Thank you so much!!

We've renamed this to options

Resources:

Thank you so much @JoviDeCroock !

Was this page helpful?
0 / 5 - 0 ratings

Related issues

k15a picture k15a  路  3Comments

paulkatich picture paulkatich  路  3Comments

adriaanwm picture adriaanwm  路  3Comments

jescalan picture jescalan  路  3Comments

Zashy picture Zashy  路  3Comments