Skip to content

Instantly share code, notes, and snippets.

@AGresvig
Last active August 29, 2015 14:11
Show Gist options
  • Save AGresvig/4968edde7a11efd8e50a to your computer and use it in GitHub Desktop.
Save AGresvig/4968edde7a11efd8e50a to your computer and use it in GitHub Desktop.
Description of Touch mixin for React. Fetched from: http://www.snip2code.com/Snippet/187682/React-js-Touch-Mixin

Handling both touch and click events in JS has always been a pain, thanks to the way these events interact. Importantly, since there are now many devices where users can both touch AND click, we can't simply switch all events over to touch events if we detect a touch. Here is the sequence these events fire:

touchstart
touchmove
touchend
-- 300ms delay --
mousedown
mousemove
mouseup
click

This presents a problem. If we bind our event handler only to click, we have a gross delay before anything happens. If we bind only to touchstart, mouse / pointer events won't fire. If we bind to both, then the handler will fire twice, once on touchstart, and then again 300ms later when click triggers.

To resolve this issue, I've put together a small mixin which sets a local variable "touched" on touchstart, and then only handles the click event if "touched" is false. In this way, the handler will only fire once, but we can bind to both touchstart and click safely.

Since React.js handles events synthetically, we need to initialize its own touch events with this line:

React.initializeTouchEvents(true);

Then we need to include the actual mixin:

var TouchMixin = {
  touched: false,
  handleTouch: function(fn) {
    this.touched = true;
    typeof fn === 'string' ? this[fn]() : this.event(fn);
  },
  handleClick: function(fn) {
    if (this.touched) return this.touched = false;
    typeof fn === 'string' ? this[fn]() : this.event(fn);
  }
};

To use the mixin, add it to the mixins array on the component, and then either add a method named "event" to the component (this is your event handler), and bind 'handleClick' onClick and 'handleTouch' onTouchStart:

mixins: [TouchMixin],
event: function() {//DO STUFF HERE},

// attach these to elements in render method
onClick={ this.handleClick } 
onTouchStart={ this.handleTouch }

Alternatively, you may wish to have a more descriptive method name, and / or multiple different event handlers. For this, bind the method name as a string to handleClick / handleTouch, and the mixin will sort it out for you:

mixins: [TouchMixin],
METHOD_NAME: function() {//DO STUFF HERE},

// attach these to elements in render method
onClick={ this.handleClick.bind(this, 'METHOD_NAME') } 
onTouchStart={ this.handleTouch.bind(this, 'METHOD_NAME') }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment