Skip to content
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

requireExternalGestureToFail is not able to block a ScrollView #3266

Open
gaearon opened this issue Dec 7, 2024 · 5 comments
Open

requireExternalGestureToFail is not able to block a ScrollView #3266

gaearon opened this issue Dec 7, 2024 · 5 comments
Labels
Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided

Comments

@gaearon
Copy link

gaearon commented Dec 7, 2024

Description

According to the docs, requireExternalGestureToFail is like the inverse of blocksExternalGesture.

However, I can't actually get requireExternalGestureToFail to do anything useful with a native gesture.

In particular, I want to block ScrollView if my Pan is being recognized.

The docs lead me to believe that this code would work:

import {View} from 'react-native'
import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView,
  ScrollView,
} from 'react-native-gesture-handler'

export default function App() {
  const pan = Gesture.Pan()
    .onBegin(() => {
      'worklet'
      console.log('begin')
    })
    .onUpdate(() => {
      'worklet'
      console.log('update')
    })
    .onEnd(() => {
      'worklet'
      console.log('end')
    })
    .onFinalize(() => {
      'worklet'
      console.log('finalize')
    })
  return (
    <GestureHandlerRootView>
      <GestureDetector gesture={pan}>
        <View style={{flex: 1, backgroundColor: 'blue'}}>
          <ScrollViewExample pan={pan} />
        </View>
      </GestureDetector>
    </GestureHandlerRootView>
  )
}

function ScrollViewExample({pan}) {
  const native = Gesture.Native().requireExternalGestureToFail(pan)
  return (
    <GestureDetector gesture={native}>
      <ScrollView
        horizontal
        pagingEnabled
        style={{
          flex: 1,
          backgroundColor: 'yellow',
        }}>
        <View
          style={{
            width: 200,
            height: '100%',
            backgroundColor: 'green',
          }}
        />
        <View
          style={{
            width: 200,
            height: '100%',
            backgroundColor: 'purple',
          }}
        />
      </ScrollView>
    </GestureDetector>
  )
}

But it doesn't do anything. The ScrollView is still in control of the gesture.

Steps to reproduce

  1. Drag the ScrollView
  2. The ScrollView gets dragged, but it should have been blocked by the Pan
this_shouldnt_be_dragggable.mov

Snack or a link to a repository

https://snack.expo.dev/k1-MTyYfvD3wQNk3sr_je

Gesture Handler version

2.20.2

React Native version

0.76.3

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Expo bare workflow

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

Real device

Device model

No response

Acknowledgements

Yes

@github-actions github-actions bot added Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided labels Dec 7, 2024
@gaearon
Copy link
Author

gaearon commented Dec 7, 2024

OMG. I accidentally imported ScrollView from RNGH (due to my IDE) and that's why it did not work. If I change the ScrollView import to be from react-native, it works. Not sure how to feel about it but this definitely simplifies things.

@j-piasecki
Copy link
Member

OMG. I accidentally imported ScrollView from RNGH (due to my IDE) and that's why it did not work. If I change the ScrollView import to be from react-native, it works. Not sure how to feel about it but this definitely simplifies things.

That's the correct thing to do if you're using the API from RNGH2 (<GestureDetector />). ScrollView exported from RNGH is a convenience wrapper that automatically wraps the ScrollView with NativeViewGestureHandler (the old API). It's kept for backwards compatibility with RNGH 1 so updates would be less painful. We are in the process of cleaning up the package for the next major and dealing with the components mess is high on the TODO list.

Anyway, it didn't work with ScrollView from RNGH because there were two native gestures attached to it - the one you created and the one from the wrapper. The one from the wrapper was deeper in the tree, so it got priority for event handling, and the relations you defined didn't get a chance to work.

Generally, if you want to use Gesture.Native on a component you shouldn't do it on components exported from RNGH as those come with it preapplied.

According to the docs, requireExternalGestureToFail is like the inverse of blocksExternalGesture.

I'll see what can be done about the docs, hopefully, we'll have them updated by the time the next major releases.

@gaearon
Copy link
Author

gaearon commented Dec 9, 2024

Ohh ok that makes sense (and yeah, not very obvious). Could GestureHandler be made to warn if its direct child is an RNGH back compat component?

It would be nice to mark those old top-level as @deprecated in TS. I did not actually realize what they were for and that they were related to an older API.

@gaearon
Copy link
Author

gaearon commented Dec 9, 2024

My two cents is that requireExternalGestureToFail docs need to show how to block native views. It is documented neither in requireExternalGestureToFail docs nor in Gesture.Native() docs. It is not obvious that they work together.

@j-piasecki
Copy link
Member

Could GestureHandler be made to warn if its direct child is an RNGH back compat component?

That should be doable, I'll need to double check whether it's detectable without any false positives (they use the same native handler under the hood).

It would be nice to mark those old top-level as @deprecated in TS. I did not actually realize what they were for and that they were related to an older API.

We are looking into updating them not to use the old API but we haven't reached any conclusions yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Platform: iOS This issue is specific to iOS Repro provided A reproduction with a snack or repo is provided
Projects
None yet
Development

No branches or pull requests

2 participants