Giter Club home page Giter Club logo

Comments (17)

kellyrmilligan avatar kellyrmilligan commented on August 23, 2024

What are you binding it to? If it's a link it will Fire twice and you have to bind to click and stop the event yourself

from react-tap-event-plugin.

watch-the-stars avatar watch-the-stars commented on August 23, 2024

No, it's just a div element and this behavior is noticed only in iOS Chrome.

from react-tap-event-plugin.

watch-the-stars avatar watch-the-stars commented on August 23, 2024

Guys, this looks like ghost click action.

from react-tap-event-plugin.

tomhicks-bsf avatar tomhicks-bsf commented on August 23, 2024

@lemmy- Can you try something? In TapEventPlugin.js around line 124, you'll see something like:

    if (isTouch(topLevelType)) {
      lastTouchEvent = nativeEvent.timeStamp
    } else {
      if (lastTouchEvent && (nativeEvent.timeStamp - lastTouchEvent) < ignoreMouseThreshold) {
        return null;
      }
    }

Try changing the lastTouchEvent = line to:

lastTouchEvent = Date.now()

and see if the problem goes away.

We've just been banging our heads against a wall with this and finally found some weird bug in UIWebView, which Chrome might be using.

from react-tap-event-plugin.

watch-the-stars avatar watch-the-stars commented on August 23, 2024

Thanks for the feedback on this issue.
I also had to hack the plugin and include it in my project codebase. So the hack looks like this.
It seems to work fine for now, but I'm not sure :) If this might cause a trouble, please, let me know.

from react-tap-event-plugin.

geekyme avatar geekyme commented on August 23, 2024

I'm getting the same issue too.

from react-tap-event-plugin.

abergs avatar abergs commented on August 23, 2024

I'm seeing this too, in Safari on Ipad with ios 8.3.

Scenario:
User clicks an <li> to open a Modal. The <li> has an onTouchTap handler (no onClick handler).
The repeated event then clicks a whatever happens to be under your finger (where we originally tapped) in the Modal. in our case another button or a input field.

I have not tried the workaround by @tomhicks-bsf

from react-tap-event-plugin.

tomhicks-bsf avatar tomhicks-bsf commented on August 23, 2024

Try this unobtrusive way of overriding the plugin (just converted from CoffeeScript so it might be a bit weird):

/*
A fix for a WebKit bug that causes all touch events to have incorrect timestamps when an app wakes
up from the background

http://stackoverflow.com/questions/26177087/ios-8-mobile-safari-wrong-timestamp-on-touch-events
 */
var EventConstants, React, TapEventPlugin, injectTapEventPlugin, isTouch, merge, oldEventExtractor, topLevelTypes;

React = require("react");

React.initializeTouchEvents(true);

merge = require("ramda").merge;

TapEventPlugin = require("react-tap-event-plugin/src/TapEventPlugin");

EventConstants = require("react/lib/EventConstants");

topLevelTypes = EventConstants.topLevelTypes;

isTouch = function(topLevelType) {
  var touchTypes;
  touchTypes = [topLevelTypes.topTouchCancel, topLevelTypes.topTouchEnd, topLevelTypes.topTouchStart, topLevelTypes.topTouchMove];
  return touchTypes.indexOf(topLevelType) >= 0;
};

oldEventExtractor = TapEventPlugin.extractEvents;

TapEventPlugin.extractEvents = function(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent) {
  if (isTouch(topLevelType)) {
    nativeEvent = merge(nativeEvent, {
      timeStamp: Date.now()
    });
  }
  return oldEventExtractor(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent);
};

injectTapEventPlugin = require("react-tap-event-plugin");

injectTapEventPlugin();

from react-tap-event-plugin.

s0meone avatar s0meone commented on August 23, 2024

I cannot reproduce this issue on iOS 8.3, iPhone 6, Chrome 42.xx. Maybe you can increase the ignore threshold?

The possible fix by @tomhicks-bsf, is now merged into master (0a29717).

from react-tap-event-plugin.

watch-the-stars avatar watch-the-stars commented on August 23, 2024

Indeed, this bug has come up unexpectedly in Chrome 41 and it seems that it works fine in 42. As far as I remember, the second event was triggered by the late native click event (ghost click), which wasn't suppressed. So increasing threshold might've helped.

from react-tap-event-plugin.

s0meone avatar s0meone commented on August 23, 2024

Alright, closing this now. Please reopen if anyone still has problems with this and cannot resolve it by increasing the threshold.

from react-tap-event-plugin.

abergs avatar abergs commented on August 23, 2024

Tried 1.7 and still had double click issues on safari ios 8.3 - @lemmy- what threshold do you mean? Could you demonstrate?

from react-tap-event-plugin.

tomhicks-bsf avatar tomhicks-bsf commented on August 23, 2024

@abergs if your rendering takes more than 750ms then you will still get the double click. You can try increasing the ignoreMouseThreshold variable in TapEventPlugin.js to see if that helps?

Also, make sure that in your project you only use onTouchTap and never onClick. The reason is that onClick handlers don't go through this plugin that 'de-dupes' pointer interactions, so you get weird behaviour. Usually this is when you render a new page, and there is a clickable element on page 2 in the same place where you did a tap on page 1.

I'm trying to think of some way we can make this less reliant on the arbitrary 750ms timeout. Perhaps by observing the time taken in the React DOM update cycle. Or at the very least, make it possible to inject the plugin with options:

var injectTapPlugin = require("react-tap-event-plugin");
injectTapPlugin({ignoreMouseThreshold: 1000}); // for slower devices

from react-tap-event-plugin.

s0meone avatar s0meone commented on August 23, 2024

@abergs Another option is to execute heavy JS in a different frame, so the browser can finish creating events before executing your event handler. I choose the value of 750ms because most handlers should be finished way before that timeout is reached, but if you're doing heavy (synchronous) stuff, the event handlers get blocked.

Like so:

handleTouchTap: function(e) {
  setTimeout(function() {
    // do heavy stuff, like a heavy React render
  }, 0);
}

By setting a timeout of zero, you'll queue the execution to the end of the execution queue.

EDIT: I've explained the above more detailed in React's issue report: facebook#2061 (comment)

from react-tap-event-plugin.

abergs avatar abergs commented on August 23, 2024

That's interesting! I wouldn't say that the rendering is slow, I believe it is under 750ms, but I can't swear on it. I'll do a test with the setTimeout just to validate that this is not the issue.

While writing this answer I re-read your answer. We do mix onClicks and onTouchTap, so that (ofcourse) might lead the problems, but it gets even deeper...

Example:
We have customs button which wraps the React.DOM.button. These have onClick props but internally wire them to onTouchTap on the DOm button. This should be OK, as of my understanding.

<OurButton onClick={handler}> => <React.dom.button onTouchTap={handler} />

But in the current scenario where we have double taps is where the button opens a dialog, and inside the dialog, at the same position as the button, we have an <Input />. And the input gets focused by the original button tap, opening the onscreen keyboard. Wouldn't there be more handlers triggering than onClick, such as onFocus causing trouble?

If that is the case, i guess you would really have to hook into reacts event system and do the de-duping - but i'm just guessing here...

from react-tap-event-plugin.

s0meone avatar s0meone commented on August 23, 2024

You're correct. The onClick on your custom button is just a prop. This can be any name you like as long as you bind this handler to onTouchTap.

We've had the exact same scenario, a button which opens a dialog with an overlay. In our case, this was quite a heavy operation, causing a parent component very high in the hierarchy to re-render. Clicking/tapping the overlay closes the dialog, so every time we opened a dialog it would close immediately. That's what I explained on React's issue and why I even patched this plugin. The example fiddle's also show this scenario. We fixed this with a setTimeout(..., 0);.

from react-tap-event-plugin.

tomhicks-bsf avatar tomhicks-bsf commented on August 23, 2024

The setImmediate solution is very interesting - I'll have to take a look into that.

We have all settled on the exact same button wrapping prop name - safety in numbers. Although we recently made a decision to ensure we don't use DOM event names for our own handlers - it creates confusion, and doesn't let us do things like linting to make sure there are no onClicks in the application layer.

We had the same issue with buttons opening dialogs and focussing inputs. The way we solved this was to add a mask to the dialog while it was animating to prevent any user interaction. The way you suggested, @s0meone, is better, although we still want to prevent any interaction during animation so the mask may well stay.

Touch events are such a minefield!

from react-tap-event-plugin.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.