Event do not trigger when node do not have "cursor: pointer" style on it.
Here you have an example:
http://jsfiddle.net/kb3gN/1345/
There is no reference to pointer (not even cursor) in the React codebase, so I'm assuming this is some weird iOS bug, React might be able to work around it though.
My guess is that is an issue that has been around for quite a while (interesting timing that I ran into the same thing for a different context this morning):
http://www.quirksmode.org/blog/archives/2010/10/click_event_del_1.html
http://stackoverflow.com/questions/7358781/tapping-on-label-in-mobile-safari
You'll see a bunch of workarounds that add empty handlers when the page loads to address this ($('label').click(function() {});)
Doesn't seem like React's problem to fix - either add 'cursor: pointer' or empty event handlers where it causes an issue.
@MattKunze We do try to fix things that can be fixed and it wouldn't surprise me if you can temporarily add a click-handler on touch and solve it like that.
Yes, we have https://github.com/facebook/react/blob/master/src/browser/eventPlugins/MobileSafariClickEventPlugin.js to fix this exact problem but it sounds like perhaps it's not working.
Is that plug-in registered automatically, or do you have to do something to enable it?
I can confirm that the original jsfiddle posted above isn't working for me on iOS
Digging through repository I found event plugin which seems to be related to similar bug:
https://github.com/facebook/react/blob/master/src/browser/eventPlugins/MobileSafariClickEventPlugin.js
But problem seems to be little wider because Chrome on iOS is also affected so this is an mobile webkit issue.
Adding
componentDidMount: function() {
this.getDOMNode().onclick = function() {}
}
to the component is a workaround. It seems like the plugin is not working at the moment
This is still not working in 0.10.0, and is actually a duplicate of #134.
Adding cursor: pointer to elements which are intended to be clickable is still the least-offensive workaround.
Ever since on-demand event listening was added, MobileSafariClickEventPlugin has been broken because touchstart isn't always listened to. cursor: pointer; is an okay workaround but we'll have to fix this for real somehow, probably by having onclick handlers turn into onclick="" markup.
This was reverted in 431155d2e231cfb65e236f9289fddf8cea291185.
Having the issue has well. And using a cursor pointer can't work in several case for me since I've set cursor to help|zoom-in in some place... :/
That would be nice that react include a awesome fix :)
After going around with this quite a bit, I'm failing to see how this is an issue. iOS seems to be following semantics here. Any element that triggers an action should be a <button> or a <a>, right? Can't we just do that and solve this?
@VinSpee
@Simek: Chrome on iOS uses UIWebView (Safari). That's why it has the same issue on this platform.
As I noted in #2931, you need to set the cursor on a non-:hover pseudo-class selector, otherwise iOS doesn't register that it's clickable.
@MoOx I would think you might be able to do something like this:
.my-clickable-thing {
cursor: pointer;
}
.my-clickable-thing:hover {
cursor: help;
}
Could React handle this by simply adding DOMNode.style.cursor = 'pointer'; to any element with an onClick handler if the user agent is an ios device? Or really any mobile device since cursor doesn't affect display on mobile?
As i understand, the click listener is attached only once. (http://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation)
So:
body{cursor:pointer;}
do the trick.
As a simple workarround specify a body class for ios and you are ready.
Registering the onClick handler isn't the problem, the problem is that iOS doesn't _think_ an element is clickable unless it has cursor: pointer is set. Setting cursor: pointer just on the body will render the whole body clickable in iOS, and every single other element in the DOM will either be clickable or not, depending on iOS's handling of inherited cursor: pointer values on child elements.
Setting cursor: pointer on any element seems like a reasonable solution, but should be probably be opt-in for now instead of a default.
My original PR #1536 should have fixed this but it was reverted because it was causing some problems internally at FB. I'll look into bringing it back so we can fix this for good.
this is so weird :(
Found this interesting link: http://www.nczonline.net/blog/2012/07/05/ios-has-a-hover-problem/
It does not talk about cursor: pointer however.
What I understand is that if an element has no cursor pointer and a click listenerr, the first click will trigger the :hover state and only the second will fire the click.
This is what happens in our app, and adding cursor: pointer managed to solve the problem: the click listener is called directly and not the :hover
@spicyj sorry i'm a bit lost in your revert reverts of reverts.
Is this finally available? Which version?
What's the overhead of adding so much click listeners everywhere? Can't we do this only on iOS ?
I don't understand the solution. Where do you add that click listener?
for example I have
<div onClick={doSomething}>
<intermediateComp>
<children/>
</intermediateComp>
</div>
When clicking on the children, the :hover is triggered (it seems to :hover the whole div actually!), but the click is only fired when reclicking the children.
Where does your solution put the click listeners exactly and why does it solve the problem?
Yes, it landed in master and will be in 0.14.
This diff adds an empty onclick listener so that Mobile Safari knows your div is clickable. This mirrors what would happen if you wrote onclick="..." directly in your HTML or called addEventListener without using React. I'm not sure how this interacts with hover.
We could probably do this only on iOS but I don't know if other browsers use similar heuristics. Hopefully this has minimal performance impact but we're planning to do some benchmarking soon and if this is significant we'll figure out a way to speed it up.
ok thanks will start using the beta then :)
Still not sure to understand on which node the onclick listener is setup. In my example the div already has one so I guess this means that all others will install the click listener?
Yes that seems to work.
I've updated the initial JSFiddle to test on iOS: http://jsfiddle.net/mgenhgpd/
This is still an issue in 0.13.3.
It's fixed in 0.14 beta and will be in the final 0.14 as well.
As my earlier comment in this thread already says.
We could probably do this only on iOS but I don't know if other browsers use similar heuristics. Hopefully this has minimal performance impact but we're planning to do some benchmarking soon and if this is significant we'll figure out a way to speed it up.
@spicyj Were you able to perform any benchmarks after this was merged?
@ustun Not on this specifically, but we have no evidence that it's a hotspot.
It's fixed in 0.14 beta and will be in the final 0.14 as well.
@spicyj onClick is still not working on iOS in 0.14.7 but fixed in 15.0. And we sill get stuck in 0.14.7 I think.
I don't know of any changes in 15.0 that would have affected this.
@spicyj I've tried with React 15.1.0 but still doesn't work in Safari 9.0.
By the way on Chrome 51.0.2 works perfectly.
Both tested into an iPad 9.1
@brunogarcia Can you post a jsfiddle or jsbin with this?
@spicyj Hi, we've made more testing with Safari (iOS 9.3.2).
We've found that Safari on private browsing doesn't save data into LocalStore.
So, it's not a React bug.
Sorry for my mistake.
This has taken my day, i had a form which was handling onSubmit first. Form was refreshing on iphone 4 even though it was executing event.preventDefault().(every other device i tested works with no problem since the beginning) Then i tried everything which i ended replacing form with a div and making the button handling onClick. I am running (react": "^15.0.1"), including cursor pointer but click event never happens so i can not execute the function. I really do not know what is left for me to try. I would wholeheartedly appreciate if i could find a solution. thanks.
I am having the same issue in react 15.0.1
@easga @tiaaaa123 If one of you can find a simple repro case (jsbin or jsfiddle), please post it and we can dig in.
@spicyj Thanks Ben. My customer was seeing this problem on iphone 4, but once i realized i could simulate that device and check the logs, i realized that my production js was having problems due the reason mentioned in this article (http://lukecod.es/2016/03/14/react-invariant-violation-minified-exception-ios8-webpack-babel/). Then i made it work. Sorry that i forgot to update it here, everything works great with React itself!
Most helpful comment
Adding
to the component is a workaround. It seems like the plugin is not working at the moment