Skip to content
This repository has been archived by the owner on Nov 27, 2022. It is now read-only.

Android crash: Animated events must have event data. #976

Closed
valeriashpiner opened this issue Feb 27, 2020 · 49 comments · Fixed by software-mansion/react-native-gesture-handler#1171
Labels

Comments

@valeriashpiner
Copy link

valeriashpiner commented Feb 27, 2020

Current behaviour

Android crashes when I scroll to the end of tabs.
It happens all the time on Android.

You scroll to the end and then you try to scroll the last item more and more few times, but it's the last item so app just crashed after few scrolls.

Expected behaviour

Android doesn't have crash when I scroll.

Screenshots (if applicable)

Screen Shot 2020-02-27 at 11 14 20 AM

It's only your library in my project which uses reanimated and react-native-gesture-handler together, and it happens on react-native-tab-view components. So I believe, it's related to your library.

What have you tried

I updated react-native-tab-view to 2.13.0.
I updated reanimated to 1.7.0.
I put import 'react-native-gesture-handler' at the top of root file index.js.
Releated issue here

Your Environment

software version
ios or android android
react-native 0.61.2
react-native-tab-view 2.11.0 and 2.13.0
react-native-gesture-handler ^1.4.1
react-native-reanimated ^1.2.0 and ^1.7.0
node 12.12.0
npm or yarn yarn
@valeriashpiner
Copy link
Author

This is also reproducible on example from this repository.

@ezechielk
Copy link

ezechielk commented Feb 29, 2020 via email

@anastely
Copy link

@valeriashpiner I don't use this library, And I got the same error 🤷‍♂️ Maybe related on react-native-gesture-handler So if you solve it, please tell me :))

@valeriashpiner
Copy link
Author

@anastely

You could use my fork: https://github.com/valeriashpiner/react-native-tab-view if you need react-native-tab-view.
I fixed it temporarily.

It's one line change there exactly in PanGestureHandler component which is part of react-native-gesture-handler. You could try it.
I checked it on a few real devices and it seems that everything works well.

@anastely
Copy link

@valeriashpiner Sadly I used react-navigation-tabs but I will give a try

@shehzabcodecraft
Copy link

@anastely Are you able to solve it? Please explain if you have done it.

@valeriashpiner
Copy link
Author

@shehzabcodecraft you could use my fork, I fixed it there.

@osdnk
Copy link
Collaborator

osdnk commented Mar 6, 2020

https://github.com/osdnk/rntv-976

cannot repro. Please provide an example.

@valeriashpiner
Copy link
Author

valeriashpiner commented Mar 6, 2020

@osdnk I just reproduced it on your repo and recorded video. To reproduce you should scroll the last screen to the right side (to next screen which obviously not exists) and vice versa.

It will exist everywhere because it exists in the original example.

@osdnk
Copy link
Collaborator

osdnk commented Mar 9, 2020

What I'm doing wrong?

https://streamable.com/tuwyc

@valeriashpiner
Copy link
Author

valeriashpiner commented Mar 9, 2020

It appears on the real device. It happened with me and also with another ppl in this thread. What the point of proving that you can't reproduce it if I already recorded video from your project that it exists there? @osdnk

@osdnk
Copy link
Collaborator

osdnk commented Mar 9, 2020

I have no problem with saying that the bug exists. But I’d like to fix it as well and stack trace is not sufficient for debugging

@valeriashpiner
Copy link
Author

Okay, @osdnk, sorry for misunderstanding:

Steps to reproduce:

  • Go to the last screen by scrolling left.
  • At the last screen, keep scrolling left more and more (even if the next screen doesn't exist.)

Maybe @ezechielk can help to explain more.

@shehzabdeveloper
Copy link

I defined swipeEnabled as false.. so this issue got a workaround

@lander854
Copy link

same problem

@EugeneDraitsev
Copy link

@osdnk It's reproduced by constantly swiping to the left on first tab or to the right on last tab, but I can reproduce it only on prod version of build. So would be nice if you can try to reproduce and maybe fix it

@melkayam92
Copy link

same here

@shehzabdeveloper
Copy link

@osdnk It's reproduced by constantly swiping to the left on first tab or to the right on last tab, but I can reproduce it only on prod version of build. So would be nice if you can try to reproduce and maybe fix it

You can disable the swipe option. "swipeEnabled" component as false will solve the crash. But after that, you cant swipe between tabs. Instead, you need to tap on the options to open tabs.

@avlonder
Copy link

Hi, is there currently a workaround that still allows swiping between tabs? For example, is there a way to catch the erroneous swipes with react-native-gesture-handler? :)

@svenlombaert
Copy link

@avlonder This workaround works, and still allows swiping:
getdelta/react-native-gesture-handler@311da06

I copied it from another fork that fixed it on an older version of react-native-gesture-handler

@jakub-gonet
Copy link

Hi guys,
I reproduced this issue on example app running in production mode. However, the app is working when I run code in create-react-app with the newest versions of Reanimated and Gesture Handler.

@valeriashpiner, @melkayam92, @anastely, @EugeneDraitsev, @svenlombaert can you guys check if this issue still exists on [email protected] and Gesture [email protected]?

@valeriashpiner
Copy link
Author

@jakub-gonet oh, I am without android device now (it's not reproducible on a simulator). I hope someone here could help!

@svenlombaert
Copy link

I don't have an android device either, but I reproduced it on [email protected] and [email protected]. From the commits I see in both patches, it would be highly unlikely it got fixed.

@2788
Copy link

2788 commented Apr 3, 2020

I reproduced it on [email protected] and [email protected].

@chgsilva
Copy link

i am still facing this issue, any news?

@raj-upadhyay
Copy link

I am still facing this issue reproduced in issue with [email protected], [email protected], and [email protected]

@pradnesh-amin
Copy link

I am still facing this issue reproduced in issue with [email protected], [email protected], and [email protected]

Yes me too..

@drb1
Copy link

drb1 commented Jun 4, 2020

"react-native-gesture-handler": "1.6.1",
"react-native-reanimated": "1.9.0",
"react-native-tab-view": "^2.13.0",

still same issue

@jakub-gonet
Copy link

@chgsilva, @raj-upadhyay, @pradnesh-amin, @drb1

this issue is probably related to gesture handler, would really appreciate some reproduction examples.

@sannajammeh
Copy link

As a temporary fix you can replace the pager component with an entirely native one: https://github.com/software-mansion-labs/react-native-tab-view-viewpager-adapter . Thus bypassing the gesture-handler itself.

@midoushitongtong
Copy link

@chgsilva, @raj-upadhyay, @pradnesh-amin, @drb1

this issue is probably related to gesture handler, would really appreciate some reproduction examples.

hi!
Please try this snack.
You just have to slide normally to see the problem.
https://snack.expo.io/@midoushitongtong/rntv-976-test

@jayzyaj
Copy link

jayzyaj commented Jul 7, 2020

any updates on this?

@leonimurilo
Copy link

Same issue here. I still did not get the pattern but I have two nested createMaterialTopTabNavigator

@rphlmr
Copy link

rphlmr commented Jul 10, 2020

I reproduce on android 10 but not on 9 and lower (physical device with expo and release build). If it helps :'(

but #976 (comment) works <3

@hamidfzm
Copy link

This bug should be fixed in react native gesture handler. This is my patch package file in order to fix the android crash. Hope it will be a useful workaround until they fix it.
https://gist.github.com/hamidfzm/b85332b6d7408307a1e250b0f2db4d7f

@OsamaMukhtar
Copy link

Needs to be fixed. Same issue here

@ShahalKP
Copy link

+1. I hope I'll notice when they patch this.

@kamalpandey
Copy link

kamalpandey commented Jul 25, 2020

Same issue. Any workaround?

"expo": "36",
 "react-native-gesture-handler": "~1.5.0",
 "react-native-reanimated": "~1.4.0",
 "react-native-tab-view": "2.15.0",
 "react-native-webview": "^7.0.5",
 "react-navigation": "^4.0.9",
 "react-navigation-stack": "^2.8.2",
 "react-navigation-tabs": "^2.9.0",

Screenshot_20200725-134535

@kamalpandey
Copy link

@sannajammeh

In IOS the keyboard opens and closes automatically but works fine if i remove it but for android I should add this as this is working. How should i deal with IOS?

More Info Here

@aliceathens
Copy link

+1

@mchambaud
Copy link

+1 still happening

jakub-gonet added a commit to software-mansion/react-native-gesture-handler that referenced this issue Aug 21, 2020
## Description

This commit fixes a threading issue connected with `enabled` property of gesture handlers. Changing this property in JS called `updateGestureHandler` in the RNGH Java module which in turn called `setEnabled`. `setEnabled` cancels handler by using `cancel()` method if it was in an active state previously.
This method was mistakenly called directly from the native modules thread - state transition methods are intended to be called from the UI thread.

This made GH orchestrator call `handler.dispatchStateChange()` on the wrong thread. This caused event listeners to receive the event on a non-UI thread (`NodeManager.onEventDispatch()` from Reanimated) via `EventDispatcher`.

Reanimated handles non-UI events in `onEventDispatch` (e.g. `onLayout` event) by adding them to the internal queue and posting frame callback if it wasn't posted previously (`onAnimationFrame()` wasn't called). Then any queued event is handled on UI thread in the next frame. 
Problem is, `EventDispatcher` first calls `onEventDispatch()` of any registered listeners and then runs `maybePostFrameCallbackFromNonUI()` which tries to post frame callback dispatching and disposing events from JS thread. 

So there was a possibility that we:
1. queue event in `NodeManager.onEventDispatch` in native modules thread
2. handle and **dispose** event in `EventDispatcher`, setting extra data to `null`
3. take the event from the queue and try handling it in the `NodeManager.onAnimationFrame`, raising exception.

The solution to that problem is to always run `cancel()` (and any other `stateChange` method) on UI thread.


- Fixes react-navigation/react-navigation/issues/6403
- Fixes satya164/react-native-tab-view/issues/976
- Fixes software-mansion/react-native-reanimated/issues/704

## Test plan

Huge thanks to the @midoushitongtong who provided small enough code example which reproduced this issue.

```jsx
import * as React from 'react';
import { View, StyleSheet, Dimensions, Text } from 'react-native';
import { TabView, SceneMap } from 'react-native-tab-view';

const FirstRoute = () => (
  <View style={[styles.scene, { backgroundColor: '#ff4081' }]}>
    <Text>aaaaa</Text>
    <Text>aaaaa</Text>
    <Text>aaaaa</Text>
    <Text>aaaaa</Text>
    <Text>aaaaa</Text>
  </View>
);

const initialLayout = { width: Dimensions.get('window').width };

const InnerTab = () => {
  const [index, setIndex] = React.useState(0);
  const [routes] = React.useState([{ key: 'first', title: 'First' }]);

  const renderScene = SceneMap({
    first: FirstRoute,
  });

  return (
    <TabView
      lazy
      navigationState={{ index, routes }}
      renderScene={renderScene}
      onIndexChange={setIndex}
      initialLayout={initialLayout}
    />
  );
};

export default () => {
  const [index, setIndex] = React.useState(0);
  const [routes] = React.useState([
    { key: 'a', title: 'a' },
    { key: 'b', title: 'b' },
    { key: 'c', title: 'c' },
  ]);

  const renderScene = SceneMap({
    a: InnerTab,
    b: InnerTab,
    c: InnerTab,
  });

  return (
    <TabView
      lazy
      navigationState={{ index, routes }}
      renderScene={renderScene}
      onIndexChange={setIndex}
      initialLayout={initialLayout}
    />
  );
};

const styles = StyleSheet.create({
  scene: {
    flex: 1,
  },
});
```


When swiping rapidly in the first or last tab app crashed. After running `cancel()` on UI thread it stopped crashing. Also made sure that the Example app still works correctly.
@lsancheztapia
Copy link

I disabled swipe and worked:
swipeEnabled={false}

@jakub-gonet
Copy link

This should be resolved by software-mansion/react-native-gesture-handler#1171

@c-goettert
Copy link

This issue is closed, but if I trace the PR from gesture-handler correctly, it was first introduced in version 1.8, while react-native-tab-view currently uses 1.6.
Are there any plans to update gesture-handler soon, to have the fix included? (Or did I misunderstand something?)

@HugoGresse
Copy link

you can specify the version yourself in the package.json

"react-native-gesture-handler": "1.9.0",

@jakub-gonet
Copy link

@c-goettert tab-view uses 1.6 but for development (in devDependencies section). RNGH version is actually ruled by your project dependency, as it's listed in peer dependencies.

@c-goettert
Copy link

@HugoGresse @jakub-gonet thanks for pointing that out! I'll try update gesture handler then. :)

braincore pushed a commit to braincore/react-native-gesture-handler that referenced this issue Mar 4, 2021
…sion#1171)

## Description

This commit fixes a threading issue connected with `enabled` property of gesture handlers. Changing this property in JS called `updateGestureHandler` in the RNGH Java module which in turn called `setEnabled`. `setEnabled` cancels handler by using `cancel()` method if it was in an active state previously.
This method was mistakenly called directly from the native modules thread - state transition methods are intended to be called from the UI thread.

This made GH orchestrator call `handler.dispatchStateChange()` on the wrong thread. This caused event listeners to receive the event on a non-UI thread (`NodeManager.onEventDispatch()` from Reanimated) via `EventDispatcher`.

Reanimated handles non-UI events in `onEventDispatch` (e.g. `onLayout` event) by adding them to the internal queue and posting frame callback if it wasn't posted previously (`onAnimationFrame()` wasn't called). Then any queued event is handled on UI thread in the next frame. 
Problem is, `EventDispatcher` first calls `onEventDispatch()` of any registered listeners and then runs `maybePostFrameCallbackFromNonUI()` which tries to post frame callback dispatching and disposing events from JS thread. 

So there was a possibility that we:
1. queue event in `NodeManager.onEventDispatch` in native modules thread
2. handle and **dispose** event in `EventDispatcher`, setting extra data to `null`
3. take the event from the queue and try handling it in the `NodeManager.onAnimationFrame`, raising exception.

The solution to that problem is to always run `cancel()` (and any other `stateChange` method) on UI thread.


- Fixes react-navigation/react-navigation/issues/6403
- Fixes satya164/react-native-tab-view/issues/976
- Fixes software-mansion/react-native-reanimated/issues/704

## Test plan

Huge thanks to the @midoushitongtong who provided small enough code example which reproduced this issue.

```jsx
import * as React from 'react';
import { View, StyleSheet, Dimensions, Text } from 'react-native';
import { TabView, SceneMap } from 'react-native-tab-view';

const FirstRoute = () => (
  <View style={[styles.scene, { backgroundColor: '#ff4081' }]}>
    <Text>aaaaa</Text>
    <Text>aaaaa</Text>
    <Text>aaaaa</Text>
    <Text>aaaaa</Text>
    <Text>aaaaa</Text>
  </View>
);

const initialLayout = { width: Dimensions.get('window').width };

const InnerTab = () => {
  const [index, setIndex] = React.useState(0);
  const [routes] = React.useState([{ key: 'first', title: 'First' }]);

  const renderScene = SceneMap({
    first: FirstRoute,
  });

  return (
    <TabView
      lazy
      navigationState={{ index, routes }}
      renderScene={renderScene}
      onIndexChange={setIndex}
      initialLayout={initialLayout}
    />
  );
};

export default () => {
  const [index, setIndex] = React.useState(0);
  const [routes] = React.useState([
    { key: 'a', title: 'a' },
    { key: 'b', title: 'b' },
    { key: 'c', title: 'c' },
  ]);

  const renderScene = SceneMap({
    a: InnerTab,
    b: InnerTab,
    c: InnerTab,
  });

  return (
    <TabView
      lazy
      navigationState={{ index, routes }}
      renderScene={renderScene}
      onIndexChange={setIndex}
      initialLayout={initialLayout}
    />
  );
};

const styles = StyleSheet.create({
  scene: {
    flex: 1,
  },
});
```


When swiping rapidly in the first or last tab app crashed. After running `cancel()` on UI thread it stopped crashing. Also made sure that the Example app still works correctly.
@Gogul-S
Copy link

Gogul-S commented Apr 22, 2021

@c-goettert tab-view uses 1.6 but for development (in devDependencies section). RNGH version is actually ruled by your project dependency, as it's listed in peer dependencies.

@jakub-gonet Will updating gesture-handler version in package.json fix the crash in production also?

@jakub-gonet
Copy link

Yes, it'll fix this issue both in the development and release versions of your app.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet