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

Swipeable renderLeftActions button not firing #3223

Closed
erie-e9 opened this issue Nov 18, 2024 · 13 comments
Closed

Swipeable renderLeftActions button not firing #3223

erie-e9 opened this issue Nov 18, 2024 · 13 comments
Assignees
Labels
Can repro It is confirmed we can reproduce the issue Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS Platform: Web

Comments

@erie-e9
Copy link

erie-e9 commented Nov 18, 2024

Description

Trying with simple example, I faced next issue, I can't trigger onPress action on renderLeftActions, only renderRightActions works fine. Even if I momentarily swap the body of both, the problem persists.
This is working fine in v2.20.2, but something crashes in 2.21.0, 2.21.1 and 2.21.2.

Video.

Simulator.Screen.Recording.-.iPhone.16.Pro.-.2024-11-18.at.13.35.23.mp4

Steps to reproduce

  1. Implement Swipeable inside a GestureHandlerRootView, with two levels of TouchableOpacity children.
  2. Swipe on the Swipeable. Both right and left TouchableOpacity can be displayed.
  3. Once the button is displayed, try to trigger onPress action.
  4. Only right onPress action works, left one seems to be blocked or under-indexed, onPress action doesn't work.

Snack or a link to a repository

https://snack.expo.io/

Gesture Handler version

2.21.0, 2.21.1 and 2.21.2

React Native version

0.76.2

Platforms

iOS

JavaScript runtime

None

Workflow

React Native (without Expo)

Architecture

Fabric (New Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

iPhone 16 Pro simulator

Acknowledgements

Yes

Copy link

Hey! 👋

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?

@github-actions github-actions bot added the Platform: iOS This issue is specific to iOS label Nov 18, 2024
@erie-e9
Copy link
Author

erie-e9 commented Nov 18, 2024

import React from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import Swipeable from 'react-native-gesture-handler/ReanimatedSwipeable';

export default function Example() {
  return (
    <View style={{ flex: 1, marginTop: 200, backgroundColor: 'red' }}>
      <Swipeable
        onSwipeableWillClose={(dir) => {
          console.log('will close', dir);
        }}
        onSwipeableWillOpen={(dir) => {
          console.log('will open', dir);
        }}
        onSwipeableOpen={(dir) => {
          console.log('open', dir);
        }}
        onSwipeableClose={(dir) => {
          console.log('close', dir);
        }}
        leftThreshold={50}
        rightThreshold={50}
        renderLeftActions={() => {
          return (
            <TouchableOpacity
              onPress={() => {
                console.log('press outer');
              }}
            >
              <View style={{ height: 80, width: 80, backgroundColor: 'yellow' }}>
                <Text>Left</Text>
              </View>
            </TouchableOpacity>
          );
        }}
        renderRightActions={() => {
          return (
            <TouchableOpacity
              onPress={() => {
                console.log('press outer');
              }}
            >
              <View style={{ height: 80, width: 80, backgroundColor: 'magenta' }}>
                <Text>Right</Text>
              </View>
            </TouchableOpacity>
          );
        }}
      >
        <TouchableOpacity
          onPress={() => {
            console.log('press outer');
          }}
        >
          <View
            style={{
              width: '100%',
              height: 80,
              backgroundColor: 'blue',
            }}
          >
            <TouchableOpacity
              onPress={() => {
                console.log('press inner');
              }}
              style={{ width: 80, height: 80, alignSelf: 'center' }}
            >
              <View style={{ width: 80, height: 80, backgroundColor: 'white' }} />
            </TouchableOpacity>
          </View>
        </TouchableOpacity>
      </Swipeable>
    </View>
  );
}

@latekvo latekvo added Platform: Web Platform: Android This issue is specific to Android Can repro It is confirmed we can reproduce the issue and removed Missing repro labels Nov 19, 2024
@latekvo latekvo self-assigned this Nov 19, 2024
@latekvo
Copy link
Contributor

latekvo commented Nov 19, 2024

Hi, could you clarify the repro you used to test this issue?
The sample you provided doesn't have interactive elements in the side action panels, so I added my own.
I can confirm the bug exists, but you also mentioned it "worked fine in 2.20.2." I couldn't find any interactive elements that worked better in version 2.20.2 than in 2.21.1. Can you let me know which interactive elements you used for testing in that version?
This information would be very helpful for resolving the issue.

@erie-e9
Copy link
Author

erie-e9 commented Nov 20, 2024

@latekvo thanks for your comment, I figured out I pasted the wrong code version, but I already updated it. I used RN's TouchOpacity, also tested it with import { TouchableOpacity } from 'react-native-gesture-handler' same error with both of them.

@sedrakk
Copy link

sedrakk commented Nov 26, 2024

I have the same issue, but surprisingly it works in Android, but doesn't work in iOS.

@latekvo
Copy link
Contributor

latekvo commented Nov 27, 2024

This is likely an issue with Animated.View, there isn't really a way around using it in ReanimatedSwipeable.
We'll have to wait for this issue to be resolved first: software-mansion/react-native-reanimated#6659

@daehyeonmun2021
Copy link

daehyeonmun2021 commented Dec 6, 2024

if you are bumped into this issue but need solve it quickly, use the old Swipeable instead as a temporary solution.
https://docs.swmansion.com/react-native-gesture-handler/docs/components/swipeable

@marthinhaugeterki
Copy link

+1

@erie-e9
Copy link
Author

erie-e9 commented Dec 21, 2024

Hey there, I just tested it with v2.21.2 and [email protected] and for me, it's working now. I'll close this bug, although I found another one with ReanimatedSwipeable related to performance in Android devices, but I'll create another issue soon, happy code!.

Check video:
Simulator Screen Recording - 16 Pro - 18 - 2024-12-21 at 16 15 15

@erie-e9 erie-e9 closed this as completed Dec 21, 2024
@lukachi
Copy link

lukachi commented Dec 22, 2024

The issue still persists for me with the same example:

    "react-native-gesture-handler": "2.21.2",
    "react-native-reanimated": "3.16.6",

@erie-e9
Copy link
Author

erie-e9 commented Dec 24, 2024

@lukachi Do you think I should reopen this issue?

Could you share more details, setup, devices where you're testing it, code or screenshots?
I'm testing it with Hermes and new arch enabled, RN latest version and now it works fine in both platforms (iOS simulator/android real device).

@deepktp
Copy link

deepktp commented Dec 24, 2024

+1

We are also heaving the same issue

@lukachi
Copy link

lukachi commented Dec 24, 2024

hi @erie-e9

package.json deps:

"dependencies": {
    "@dev-plugins/react-navigation": "^0.0.6",
    "@dev-plugins/react-query": "^0.0.6",
    "@distributedlab/tools": "^1.0.0-rc.16",
    "@gorhom/bottom-sheet": "^5.0.6",
    "@hookform/resolvers": "^3.9.0",
    "@react-native-community/hooks": "^3.0.0",
    "@react-native/js-polyfills": "^0.74.85",
    "@react-navigation/bottom-tabs": "7.0.0-rc.33",
    "@react-navigation/elements": "2.0.0-rc.25",
    "@react-navigation/native": "7.0.0-rc.20",
    "@react-navigation/native-stack": "7.0.0-rc.27",
    "@shopify/flash-list": "^1.7.2",
    "@tanstack/react-query": "^5.51.9",
    "app-icon-badge": "^0.0.15",
    "axios": "^1.7.2",
    "babel-preset-expo": "~12.0.3",
    "burnt": "^0.12.2",
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.1.1",
    "constants-browserify": "^1.0.0",
    "ethers": "^6.13.2",
    "expo": "52.0.14",
    "expo-asset": "~11.0.1",
    "expo-blur": "~14.0.1",
    "expo-build-properties": "~0.13.1",
    "expo-clipboard": "~7.0.0",
    "expo-constants": "~17.0.3",
    "expo-dev-client": "~5.0.5",
    "expo-file-system": "~18.0.4",
    "expo-font": "~13.0.1",
    "expo-haptics": "~14.0.0",
    "expo-image": "2.0.3",
    "expo-linking": "~7.0.3",
    "expo-local-authentication": "~15.0.1",
    "expo-secure-store": "~14.0.0",
    "expo-splash-screen": "^0.29.13",
    "expo-status-bar": "~2.0.0",
    "expo-system-ui": "~3.0.7",
    "expo-updates": "~0.26.9",
    "expo-web-browser": "~14.0.1",
    "i18next": "^23.11.5",
    "jsona": "^1.12.1",
    "lodash": "^4.17.21",
    "mrz": "^4.2.0",
    "nativewind": "4.1.21",
    "os-browserify": "^0.3.0",
    "path-browserify": "^1.0.1",
    "react": "18.3.1",
    "react-dom": "18.3.1",
    "react-hook-form": "^7.52.1",
    "react-i18next": "^14.1.2",
    "react-native": "0.76.3",
    "react-native-avoid-softinput": "7.0.0",
    "react-native-crypto": "^2.2.0",
    "react-native-gesture-handler": "2.21.2",
    "react-native-get-random-values": "^1.11.0",
    "react-native-linear-gradient": "^2.8.3",
    "react-native-mmkv": "3.1.0",
    "react-native-quick-base64": "^2.1.2",
    "react-native-reanimated": "3.16.6",
    "react-native-reanimated-carousel": "4.0.0-canary.22",
    "react-native-restart": "^0.0.27",
    "react-native-safe-area-context": "4.14.0",
    "react-native-screens": "4.3.0",
    "react-native-toast-message": "^2.2.0",
    "react-native-vision-camera": "4.6.3",
    "react-native-vision-camera-text-recognition": "^3.1.1",
    "react-native-worklets-core": "1.5.0",
    "react-native-zip-archive": "^7.0.1",
    "readable-stream": "^4.5.2",
    "stream-http": "^3.2.0",
    "tailwind-merge": "^2.4.0",
    "tailwind-variants": "^0.2.1",
    "tailwindcss": "^3.4.5",
    "tailwindcss-animate": "^1.0.7",
    "tinycolor2": "^1.6.0",
    "uuid": "^10.0.0",
    "yup": "^1.4.0",
    "zod": "^3.23.8",
    "zustand": "^4.5.4"
  },
  "devDependencies": {
    "@babel/core": "^7.24.6",
    "@expo/config": "~10.0.5",
    "@expo/config-plugins": "^9.0.11",
    "@expo/metro-config": "~0.19.5",
    "@expo/metro-runtime": "~4.0.0",
    "@react-native/eslint-config": "^0.76.5",
    "@react-native/eslint-plugin": "^0.76.5",
    "@tanstack/eslint-plugin-query": "^5.51.10",
    "@testing-library/jest-dom": "^6.4.6",
    "@typechain/ethers-v6": "^0.5.1",
    "@types/eslint": "^8.56.10",
    "@types/jest": "^29.5.12",
    "@types/lodash": "^4",
    "@types/path-browserify": "^1",
    "@types/react": "~18.3.12",
    "@types/react-native-get-random-values": "^1.8.2",
    "@types/readable-stream": "^4",
    "@types/tinycolor2": "^1",
    "@types/uuid": "^10",
    "@typescript-eslint/eslint-plugin": "^8.18.1",
    "@typescript-eslint/parser": "^8.18.1",
    "babel-plugin-module-resolver": "^5.0.2",
    "cross-env": "^7.0.3",
    "dotenv": "^16.4.5",
    "dotenv-cli": "^7.4.2",
    "eslint": "^8.57.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-i18n-json": "^4.0.0",
    "eslint-plugin-jest": "^28.6.0",
    "eslint-plugin-prettier": "^5.1.3",
    "eslint-plugin-simple-import-sort": "^12.1.1",
    "eslint-plugin-testing-library": "^6.2.2",
    "eslint-plugin-unused-imports": "^4.1.4",
    "expo-atlas": "^0.4.0",
    "expo-module-scripts": "^3.5.2",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "jest-expo": "~52.0.2",
    "jest-junit": "^16.0.0",
    "np": "^10.0.7",
    "prettier": "^3.3.3",
    "prettier-plugin-tailwindcss": "^0.6.5",
    "react-native-svg": "15.9.0",
    "react-native-svg-transformer": "^1.5.0",
    "ts-jest": "^29.1.2",
    "typechain": "^8.3.2",
    "typescript": "~5.3.3"
  },

snippet:

export default function Chats() {
  const insets = useSafeAreaInsets()
  const bottomBarOffset = useBottomBarOffset()

  const { data: fakeUsers } = useLoading([], () => getFakeUser(24), {
    loadOnMount: true,
  })

  return (
    <UiScreenScrollable>
      <View
        style={{
          paddingTop: insets.top,
          paddingBottom: bottomBarOffset,
        }}
        className='flex flex-1'
      >
        <View className='flex flex-1'>
          <FlashList
            data={fakeUsers}
            estimatedItemSize={75}
            renderItem={({ item, index }) => (
              // TODO: replace by Reanimated Swipeable once it's stable and fixed left actions
              <Swipeable
                friction={2}
                enableTrackpadTwoFingerGesture
                rightThreshold={40}
                leftThreshold={40}
                renderLeftActions={() => (
                  <View className='flex h-full flex-row items-center'>
                    <TouchableOpacity
                      className='flex min-w-[60] items-center justify-center self-stretch bg-textSecondary'
                      onPress={() => console.log('delete')}
                    >
                      <UiIcon customIcon='message' size={24} className='text-baseWhite' />
                    </TouchableOpacity>
                    <TouchableOpacity
                      className='flex min-w-[60] items-center justify-center self-stretch bg-successDark'
                      onPress={() => console.log('delete')}
                    >
                      <UiIcon
                        libIcon='FontAwesome'
                        name='bookmark'
                        size={24}
                        className='text-baseWhite'
                      />
                    </TouchableOpacity>
                  </View>
                )}
                renderRightActions={() => (
                  <View className='flex h-full flex-row items-center'>
                    <TouchableOpacity
                      className='flex min-w-[60] items-center justify-center self-stretch bg-warningMain'
                      onPress={() => console.log('delete')}
                    >
                      <UiIcon
                        libIcon='FontAwesome'
                        name='volume-off'
                        size={24}
                        className='text-baseWhite'
                      />
                    </TouchableOpacity>
                    <TouchableOpacity
                      className='flex min-w-[60] items-center justify-center self-stretch bg-errorMain'
                      onPress={() => console.log('delete')}
                    >
                      <UiIcon
                        libIcon='FontAwesome'
                        name='trash'
                        size={24}
                        className='text-baseWhite'
                      />
                    </TouchableOpacity>
                    <TouchableOpacity
                      className='flex min-w-[60] items-center justify-center self-stretch bg-textSecondary'
                      onPress={() => console.log('delete')}
                    >
                      <UiIcon
                        libIcon='FontAwesome'
                        name='archive'
                        size={24}
                        className='text-baseWhite'
                      />
                    </TouchableOpacity>
                  </View>
                )}
              >
                <ListItem
                  key={index}
                  title={item.name.first}
                  text='lorem ipsum dolor sit amet concestetur'
                  updatedAt={item.registered.date}
                  avatarUri={item.picture.thumbnail}
                  newMsgAmount={index % 2 === 0 ? 1 : undefined}
                  isRead={index % 2 !== 0}
                  className={cn(
                    'bg-backgroundPrimary',
                    index !== fakeUsers.length - 1 && 'border-b border-borderPrimary',
                  )}
                />
              </Swipeable>
            )}
          />
        </View>
      </View>
    </UiScreenScrollable>
  )
}

so, the current state is - if we use deprecated Swipeable - left action works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Can repro It is confirmed we can reproduce the issue Platform: Android This issue is specific to Android Platform: iOS This issue is specific to iOS Platform: Web
Projects
None yet
7 participants