-
Notifications
You must be signed in to change notification settings - Fork 24.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pressable has unchangeable delay for opacity effect (onPressIn) #29376
Comments
Still finding this same problem with 0.63.1, and so far the only work around is to monkey patch it to add a default 0 delay. Note that I'm seeing the odd delay even with TouchableOpacity, not just with Pressables |
@cristianoccazinsp How did you patch the delay on the Pressable? |
I have only patched the Touchable components since I didn't migrate to Pressable (yet), but I'm seeing the exact same issue, and I would guess that Touchables are using Pressable behind the scenes? My only work around was to patch the default props like this:
|
I am having the same problem. TouchableOpacity is not using Pressable but Pressabilitty API (The same one TouchableOpacity use). That said, Pressable use a hook to use the API, TouchableOpacity is a Class comoponent so it uses the class alternative to use the API. (i don't know if there is any difference between them). Looking to the source code, I can't find a prop or even a reference to a "press in delay". I hope the add such a prop, otherwise Pressable is not usefull for me. |
Pressability.js contains the prop. Changing this manually (e.g.: on a TouchableOpacity) will remove the delay, and everything works as expected. On a component, you can't set this prop (yet), making it unusable. |
#29395 I've created a pull request to add "delayPressIn" to Pressable. |
I seem to be getting a delay for Why on earth would you introduce a default delay on this? Surely the whole point of |
I believe the change was made on Pressability API, which all Touchables use. But you can set delayPressIn={0} to fix it. |
While not much better than a monkey-patch, you can use We recently upgraded from Looks like this delay option was added here with a sensible default of I'm guessing the idea of this delay is to avoid a technically incorrect visual response of a touch on a child touchable during a scroll swipe, since the touch events first goes to the child before being correctly captured by the parent Either way it's a significant change from the previous default, unintended or not, that should either by identified on changelog (I checked a few times and didn't see it), or reverted and re-introduced with the change made clear to developers. Edit: Fixed link to when delay option added |
@jehartzog That's the only use case that would make sense, and even then an opt-in would be a way better option. If I actually have the use case of the scroll view, I can manually increase the pressable's delay instead of the other way around. |
This seems like a major regression, especially when navigation is involved. Buttons don't have a chance to highlight before new screens render, making the entire interface feel static and non interactive. Note that we don't even use Adding Perhaps @yungsters might know more about this? |
Thanks for the tag, @andreialecu. I'd like to share some history, the purpose of the delay, what changed recently, and what I propose that we do next. The default "press in" delay of 130ms was always in Touchable.Mixin, but it was accidentally always overridden to zero by TouchableWithoutFeedback, et al. The purpose of this delay is to prevent accidental activations when a user initiates a scroll gesture. For example, if you have a Keep in mind that when a "press out" is detected within the 130ms, we immediately fire The fix for preserving the default press in duration was only intended for There is still the remaining question of what the default behavior for One thing we could do is change Curious to hear what everyone thinks. Thanks! |
@yungsters Thanks for writeup. There are many cases where having this I do recognize the desire to avoid the undesired My recommendation:
Developers who care to actually clean up their UI as much as possible will be able to opt-in to this when needed, and there are no chances of missing the much more important If you do decide to add the behavior to auto apply |
I'm not sure this would help. In my experience most pressables would be nested inside The most noticeable issue I saw from the added delay in 0.63 was that It would also make it inconsistent and I feel users wouldn't understand what's going on. I have been looking at how other apps do it for a bit, and I noticed that in Outlook for iOS for example, when you tap an email, there's a slight delay (several miliseconds) before it navigates to the screen that shows the email. It's enough time to show visual indication that you tapped on something. And there are no "accidental activations" when scrolling. Note that I have no experience with How about something like this:
Would this not work? (Note that there would need to be a way to prevent repeated taps from triggering |
Thanks for the thoughtful (and extremely prompt) responses. Let me first respond to @andreialecu. Your realization that As for next steps, we feel pretty strongly that the delay should be the new default in If this makes sense, my proposal is the following:
As a net effect, Does this seem reasonable? |
Would it not work to keep the delay as it is and add an additional delay before |
@andreialecu We do not actually want to delay the navigation, though. That would make the end user experience worse by actually delaying the navigation and initialization of the next surface. |
@yungsters I'm a fan of your proposal, as it is likely to improve future UI without requiring a full audit of existing |
@yungsters would it be noticeable though? If it can be made fast enough that In my experience react native click handlers actually somehow feel too fast compared to other (native) apps when initiating navigation (using react-navigation). In other apps there seems to be an additional delay of several milliseconds (16ms, one frame?) which I associated with them waiting to ensure the feedback is displayed. |
@yungsters Here's a possibly better explanation since I was on mobile yesterday: Scenario A:
Scenario B
I think scenario A is preferrable for when pressables are nested inside
Since Scenario A should only add a few extra frames of delay (out of 60fps), I think it can be defaulted for existing Wouldn't this be much better for UX? |
@andreialecu not everyone wants an additional delay for Pressables. In some (most) cases you want the |
@mrousavy that won't work in most cases unfortunately. There are thousands of pre-existing react native libraries using The delay I'm proposing should be absolutely non-noticeable and would make react-native touchables behave more like "native-native" touchables. To keep it inline with @yungsters's proposal, the delay could be "smart" and only be applied when nested in a Additionally, someone could handle |
Delaying |
Apologies but I don't understand. I feel we may not be talking about the same issue. I tried rereading this:
I'm not sure what this has to do with anything. By reversing/popping the navigation I understand going back to a previous screen. The issue at hand is that buttons don't get a chance to update to active/touched state before navigating to a new screen ("pushing" a screen) or before going back ("pulling"/"popping"). The issue here is not isolated to navigation though. I noticed it in a lot of other components that are unrelated to navigation, and which need to be nested in ScrollViews. With your proposed approach there's still no way to have Touchables behave properly within ScrollViews. They would still show no feedback unless What am I missing? (As a side note, this isn't limited to iOS. The same problem exists on Android) |
GIF to demonstrate the problem: New delay as per RN 63: Using .patch by @jehartzog above to revert the 130ms delay back to 0: This is a "Drawer" type screen which is not necessarily navigation. (Arguably it's not in a ScrollView here.)
But consider a "call to action" button as part of a ScrollView below, maybe "Open Details" -> which also opens this side drawer, but it's not navigation, just an animated overlay. Would hooking it up to navigations make any difference and automatically handle this? Here's an example from Android System Settings: It looks like the navigation is delayed for a little bit after the tap. The ripple even gets a chance to complete. In my experience react-native triggers |
I don't know how, but when I add onPress handler to Pressable. dealy suddenly gone |
I feel like compensating for being inside a scrollable container is the more unusual case (I checked several RN codebases I maintain and it was something like 5:1), which makes me think the default behaviour should be no delay, with a prop that can be used to add a delay if required. Maybe something like |
I can confirm that adding an However I believe this is probably unintentional and it would be great if the root cause is fixed instead. FYI, I am using |
That's not a workaround, cause that's not expected behavior. Adding or not an onPress handler should not change the press in delay. |
Yes - I actually meant "quick hack" (to eliminate the delay) instead - editing to avoid confusion. And I agree that this should be fixed properly instead (say, by exposing an optional prop |
FWIW, sharing how UIKIt handles this: by default, press interactions on buttons are delayed when they're inside of scroll views (and not otherwise). |
I have a new project where I used the new Pressable component in several places, but then I started noticing the delay discussed here. After reading through the comments, I've replaced all the Pressable components with TouchableOpacity components with |
Will you add this to a coming release? |
Yes, definitely. |
Sorry for the radio silence. Let me share my latest plans on this. In order to avoid the unwanted breaking changes, I am going to rollback the default delay in the upcoming release. In addition, I am adding a new |
There is an awesome component by the name of RectButton inside react-native-gesture-handler which have performant ripple animation in android and highlight animation in ios. I know that it's not related to this thread but maybe it helps some one |
After providing delayPressIn={0} to touchable opacity I am still getting the delay in my entire app and it is really a frustrating thing. This delay increases with usage , the more i press buttons delay it is providing to me in next press. |
I used the Pressable onTouchStart event to remove the delay for onPressIn Events |
Summary: Removes the default press delay from `Pressability`, which was introduced in 0.63 and affected `Pressable`. Fixes #29376. In a subsequent commit, I will bring it back as an `unstable_pressDelay` prop. Changelog: [General][Changed] - Removed default 130ms delay from Pressability and Pressable. Reviewed By: lunaleaps Differential Revision: D23604582 fbshipit-source-id: c21c72bf8b59fed028f5905ca4f805bb3fa79399
Is it resolved or should i downgrade my react native version? Because it is really annoying. |
@GuleriaAshish The |
Fixed in v0.63.3, recommend closing this issue:
|
Summary: Removes the default press delay from `Pressability`, which was introduced in 0.63 and affected `Pressable`. Fixes facebook#29376. In a subsequent commit, I will bring it back as an `unstable_pressDelay` prop. Changelog: [General][Changed] - Removed default 130ms delay from Pressability and Pressable. Reviewed By: lunaleaps Differential Revision: D23604582 fbshipit-source-id: c21c72bf8b59fed028f5905ca4f805bb3fa79399
Description
The
<Pressable />
component has an unchangeable delay between pressing and visual feedback.See:
As you can see, the
TouchableOpacity
has instant visual feedback when I press it, where as the Pressable takes about120
ms (wild guess).I though 49b2a6e should fix this delay?
React Native version:
Steps To Reproduce
Provide a detailed list of steps that reproduce the issue.
<Pressable />
componentpressed
argumentExpected Results
The opacity effect/visual feedback should appear instantly, like on the TouchableOpacity.
Snack, code example, screenshot, or link to a repository:
PressableOpacity.ts
:Now just use it:
App.js
The text was updated successfully, but these errors were encountered: