satya164 / react-native-tab-view

A cross-platform Tab View component for React Native
MIT License
5.14k stars 1.07k forks source link

[V3] Random onPress handle in FlatList items while swiping tabs #1241

Open a-sane opened 3 years ago

a-sane commented 3 years ago

Current behavior

Random onPress handle in FlatList items while swiping tabs after V3 update Especially noticeable on low-end android devices and in apps with many heavy components

Related issue: https://github.com/callstack/react-native-pager-view/issues/424

Example:

There is a function in demo that imitate CPU intensive operation in order for the issue to be stably reproduced in simple demo on high-end devices

https://snack.expo.dev/@sane.ecg/tab-nav-onpress-issue

https://user-images.githubusercontent.com/764967/128614536-3259f49a-0d80-480c-b12a-24b9e4d708c1.mp4

More real world example with react navigation V6:

https://snack.expo.dev/@sane.ecg/v6-tab-nav-issue

https://user-images.githubusercontent.com/764967/128614696-d46d2737-f801-4749-897a-5cc5e80798db.mp4

Expected behavior

No random onPress handle like in V2

https://user-images.githubusercontent.com/764967/128614762-807a60f5-06c7-4d59-9929-8eb36ff5c438.mp4

https://snack.expo.dev/@sane.ecg/tab-nav-v2-no-onpress-issue

Reproduction

https://snack.expo.dev/@sane.ecg/tab-nav-onpress-issue

Platform

Environment

package version
react-native 0.64.2
react-native-tab-view 3.1.1
react-native-pager-view 5.4.0
expo 42.0.3
github-actions[bot] commented 3 years ago

Couldn't find version numbers for the following packages in the issue:

Can you update the issue to include version numbers for those packages? The version numbers must match the format 1.2.3.

The versions mentioned in the issue for the following packages differ from the latest versions on npm:

Can you verify that the issue still exists after upgrading to the latest versions of these packages?

matfin commented 3 years ago

I am getting the same behaviour. When I have a <TouchableOpacity /> inside a view that is contained in react-native-tab-view, an onPress is triggered as I swipe through the three views in the tab view container.

I am using React Native 0.64.2 and I have the Hermes Javascript engine enabled.

kashmiry commented 3 years ago

Facing the same issue on iOS and Android after upgrading to V3. Button inside flat list get pressed while swiping.

darrychen92 commented 3 years ago

Got the same issue. Have you fixed it?

alantoa commented 2 years ago

same issue...

itsramiel commented 2 years ago

same issue

salonisahu commented 2 years ago

Any update?

Gregoirevda commented 2 years ago

Found a solution! Replace <TouchableHighlight with <FixedTouchableHighlight in your FlatList

// FixedTouchableHighlight.js
import React, { useRef } from 'react';
import { TouchableHighlight } from 'react-native';

export default function FixedTouchableHighlight({
  onPress,
  onPressIn,
  ...props
}) {
  const _touchActivatePositionRef = useRef(null);

  function _onPressIn(e) {
    const { pageX, pageY } = e.nativeEvent;

    _touchActivatePositionRef.current = {
      pageX,
      pageY,
    };

    onPressIn?.(e);
  }

  function _onPress(e) {
    const { pageX, pageY } = e.nativeEvent;

    const absX = Math.abs(_touchActivatePositionRef.current.pageX - pageX);
    const absY = Math.abs(_touchActivatePositionRef.current.pageY - pageY);

    const dragged = absX > 2 || absY > 2;
    if (!dragged) {
      onPress?.(e);
    }
  }

  return (
    <TouchableHighlight onPressIn={_onPressIn} onPress={_onPress} {...props}>
      {props.children}
    </TouchableHighlight>
  );
}
patrik-u commented 2 years ago

Found a solution! Replace <TouchableHighlight with <FixedTouchableHighlight in your FlatList

Thanks, worked perfectly. In my case I wrapped TouchableOpacity and TouchableWithoutFeedback in the same way.

ProkhoDim commented 2 years ago

Found a solution! Replace <TouchableHighlight with <FixedTouchableHighlight in your FlatList

// FixedTouchableHighlight.js
import React, { useRef } from 'react';
import { TouchableHighlight } from 'react-native';

export default function FixedTouchableHighlight({
  onPress,
  onPressIn,
  ...props
}) {
  const _touchActivatePositionRef = useRef(null);

  function _onPressIn(e) {
    const { pageX, pageY } = e.nativeEvent;

    _touchActivatePositionRef.current = {
      pageX,
      pageY,
    };

    onPressIn?.(e);
  }

  function _onPress(e) {
    const { pageX, pageY } = e.nativeEvent;

    const absX = Math.abs(_touchActivatePositionRef.current.pageX - pageX);
    const absY = Math.abs(_touchActivatePositionRef.current.pageY - pageY);

    const dragged = absX > 2 || absY > 2;
    if (!dragged) {
      onPress?.(e);
    }
  }

  return (
    <TouchableHighlight onPressIn={_onPressIn} onPress={_onPress} {...props}>
      {props.children}
    </TouchableHighlight>
  );
}

Thanks!!