-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Animated events must have event data #704
Animated events must have event data #704
Comments
I dont't know how to reproduce this issue, because this error stack is reported by a bug analysis system. |
All right, could you provide packages versions then? It was happening before or after you upgraded to certain version of gesture handler / reanimated? |
I upgrade react-native to 0.62 last week. |
It's probably related to this issue |
same issue here, any solutions? |
@chgsilva, If you have reproducible code that causes the crash and can be debugged it'd be really appreciated. |
same issue in release mode, is there any solution |
same in Android
|
+1 same issues for our app in production:
|
|
I'm keeping eye on this issue, but any reproduction example would be very helpful. |
@Override
public void receiveEvent(int targetTag, String eventName, @Nullable WritableMap event) {
if (event == null) {
// throw new IllegalArgumentException("Animated events must have event data.");
return;
}
for (int i = 0; i < mMapping.size(); i++) {
EventMap eventMap = mMapping.get(i);
Double value = eventMap.lookupValue(event);
if (value != null) {
mNodesManager.findNodeById(eventMap.nodeID, ValueNode.class).setValue(value);
}
}
} Don't throw an exception here. This caused a large number of crash 😂 |
@kangfenmao, as I said here I'd want to fix the root of the problem instead of ignoring malformed events. |
Hi guys, could you check if software-mansion/react-native-gesture-handler#1171 fixes those crashes for you? |
## 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.
Will a release be created with this fix? |
In the near future, yes. We need to make sure that changing state of gestures are done from one thread and this needs a little bit more testing. |
@jakub-gonet hello! is it fixed for now moment? some of our users with Android has:
|
Fix for that crash was included in the 1.8.1 release of the gesture handler. |
…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.
Hi @jakub-gonet there no version |
You can install any version from 1.8.0 upwards. |
Thanks, @jakub-gonet |
The text was updated successfully, but these errors were encountered: