Fix issue with navigation immediately on mount

https://github.com/react-navigation/react-navigation/issues/5247
This commit is contained in:
Brent Vatne 2018-11-30 12:03:17 -08:00
parent 5780c0e0d1
commit 825ba5b6f5
3 changed files with 129 additions and 2 deletions

View File

@ -33,7 +33,6 @@ import { useScreens } from 'react-native-screens';
// Uncomment the following line to force RTL. Requires closing and re-opening
// your app after you first load it with this option enabled.
I18nManager.forceRTL(false);
useScreens();
const data = [
{ component: SimpleStack, title: 'Simple', routeName: 'SimpleStack' },
@ -146,3 +145,8 @@ const Root = createStackNavigator(
const App = createAppContainer(Root);
Expo.registerRootComponent(App);
useScreens();
// Uncomment this to test immediate transitions
// import ImmediateTransition from './src/ImmediateTransition';
// Expo.registerRootComponent(ImmediateTransition);

View File

@ -0,0 +1,110 @@
import React, { Component } from 'react';
import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer } from '@react-navigation/native';
import {
Platform,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
class ScreenOne extends React.Component {
componentDidMount() {
this._timer = setTimeout(() => {
this.props.navigation.navigate('Screen2');
clearTimeout(this._timer);
}, 0);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>Here is Screen One!</Text>
<TouchableOpacity
style={styles.button}
onPress={() => {
this.props.navigation.navigate('Screen2');
}}
>
<Text style={{ color: 'white', fontSize: 24 }}>Press me!</Text>
</TouchableOpacity>
</View>
);
}
}
class ScreenTwo extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>Here is Screen Two!</Text>
<TouchableOpacity
style={styles.button}
onPress={() => {
this.props.navigation.navigate('Screen3');
}}
>
<Text style={{ color: 'white', fontSize: 24 }}>Press me!</Text>
</TouchableOpacity>
</View>
);
}
}
class ScreenThree extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>Here is Screen Three!</Text>
</View>
);
}
}
export const Stack = createStackNavigator(
{
Screen1: { screen: ScreenOne },
Screen2: { screen: ScreenTwo },
Screen3: { screen: ScreenThree },
},
{
initialRouteName: 'Screen1',
defaultNavigationOptions: {
header: null,
},
}
);
const PrimaryStack = createAppContainer(Stack);
export default PrimaryStack;
const styles = StyleSheet.create({
button: {
height: 50,
width: 200,
backgroundColor: 'dodgerblue',
justifyContent: 'center',
alignItems: 'center',
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});

View File

@ -111,6 +111,14 @@ class Transitioner extends React.Component {
// prevTransitionProps are the same as transitionProps in this case
// because nothing changed
this._prevTransitionProps = this._transitionProps;
// Unsure if this is actually a good idea... Also related to
// https://github.com/react-navigation/react-navigation/issues/5247
// - the animation is interrupted before completion so this ensures
// that it is properly set to the final position before firing
// onTransitionEnd
this.state.position.setValue(props.navigation.state.index);
this._onTransitionEnd();
return;
}
@ -190,7 +198,12 @@ class Transitioner extends React.Component {
timing(position, {
...transitionSpec,
toValue: nextProps.navigation.state.index,
}).start(this._onTransitionEnd);
}).start(() => {
// In case the animation is immediately interrupted for some reason,
// we move this to the next frame so that onTransitionStart can fire
// first (https://github.com/react-navigation/react-navigation/issues/5247)
requestAnimationFrame(this._onTransitionEnd);
});
} else {
this._onTransitionEnd();
}