mirror of
https://github.com/status-im/react-navigation-stack.git
synced 2025-02-11 05:56:36 +00:00
Clean up transitioner a bit, fix issue where state is invalid and warn
This commit is contained in:
parent
a9f6d467d2
commit
c27ed1b4b8
@ -15,6 +15,7 @@ import ModalStack from './src/ModalStack';
|
||||
import LifecycleInteraction from './src/LifecycleInteraction';
|
||||
import GestureInteraction from './src/GestureInteraction';
|
||||
import SwitchWithStacks from './src/SwitchWithStacks';
|
||||
import StackWithDrawer from './src/StackWithDrawer';
|
||||
|
||||
// Comment the following two lines to stop using react-native-screens
|
||||
import { useScreens } from 'react-native-screens';
|
||||
@ -48,6 +49,11 @@ const data = [
|
||||
title: 'Switch with Stacks',
|
||||
routeName: 'SwitchWithStacks',
|
||||
},
|
||||
{
|
||||
component: StackWithDrawer,
|
||||
title: 'Stack with drawer inside',
|
||||
routeName: 'StackWithDrawer',
|
||||
},
|
||||
];
|
||||
|
||||
// Cache images
|
||||
|
@ -17,7 +17,9 @@
|
||||
"react": "16.3.1",
|
||||
"react-native": "~0.55.4",
|
||||
"react-native-paper": "2.0.0-alpha.4",
|
||||
"react-native-screens": "^1.0.0-alpha.9"
|
||||
"react-native-screens": "^1.0.0-alpha.9",
|
||||
"react-navigation-drawer": "^1.0.0-alpha",
|
||||
"react-navigation-tabs": "^1.0.0-alpha"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-plugin-module-resolver": "^3.0.0",
|
||||
|
48
example/src/StackWithDrawer.js
Normal file
48
example/src/StackWithDrawer.js
Normal file
@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { Button, Text, View } from 'react-native';
|
||||
import { createStackNavigator } from 'react-navigation-stack';
|
||||
import { createDrawerNavigator } from 'react-navigation-drawer';
|
||||
import { createBottomTabNavigator } from 'react-navigation-tabs';
|
||||
|
||||
function Menu({ navigation }) {
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<Button title="Open on top" onPress={() => navigation.navigate('Top')} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
class Fake extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
||||
<Text style={{ fontSize: 20 }}>
|
||||
{this.props.navigation.getParam('title')}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const Tab = createBottomTabNavigator({
|
||||
Home: { screen: Fake, params: { title: 'Home' } },
|
||||
Other: { screen: Fake, params: { title: 'Other' } },
|
||||
});
|
||||
|
||||
const Drawer = createDrawerNavigator(
|
||||
{
|
||||
TabScreen: {
|
||||
screen: Tab,
|
||||
},
|
||||
},
|
||||
{
|
||||
contentComponent: props => <Menu {...props} />,
|
||||
}
|
||||
);
|
||||
|
||||
const App = createStackNavigator({
|
||||
Drawer: { screen: Drawer },
|
||||
Top: { screen: Fake, params: { title: 'Top' } },
|
||||
});
|
||||
|
||||
export default App;
|
@ -4353,6 +4353,13 @@ react-native-svg@6.2.2:
|
||||
lodash "^4.16.6"
|
||||
pegjs "^0.10.0"
|
||||
|
||||
react-native-tab-view@^1.0.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-1.2.0.tgz#0cc26a1c8e49b6c0d58a30363dbbe43954907c31"
|
||||
integrity sha512-lpiWi3dog86Fu/W60DU12RKrFv3XuTv0lHMC56t2jlDqxLfVzG9ufV7li6Afl2S2ZicNU1Bob8WPgxVZc8egAA==
|
||||
dependencies:
|
||||
prop-types "^15.6.1"
|
||||
|
||||
react-native-vector-icons@4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-4.5.0.tgz#6b95619e64f62f05f579f74a01fe5640df95158b"
|
||||
@ -4427,6 +4434,21 @@ react-native@~0.55.4:
|
||||
xmldoc "^0.4.0"
|
||||
yargs "^9.0.0"
|
||||
|
||||
react-navigation-drawer@^1.0.0-alpha:
|
||||
version "1.0.0-alpha.5"
|
||||
resolved "https://registry.yarnpkg.com/react-navigation-drawer/-/react-navigation-drawer-1.0.0-alpha.5.tgz#1ef75b5e9c7ae9c3011427a493bcc2714ea2c072"
|
||||
integrity sha512-AD1AyqGpUb4coUw3KpJ7i/2RfTiE5RJfTDHVeBkpqc2wsXJ4PaWYGoxfvfWP910hJy8txYTnWWUinWmiD7aBgA==
|
||||
|
||||
react-navigation-tabs@^1.0.0-alpha:
|
||||
version "1.0.0-alpha.4"
|
||||
resolved "https://registry.yarnpkg.com/react-navigation-tabs/-/react-navigation-tabs-1.0.0-alpha.4.tgz#321c8cc19d14268d343a830689c741bb94c6ba80"
|
||||
integrity sha512-ng8sCJmcQj1ciWaj0eJudQvYng/oL24konNPNudSrMyVKAfKr4+HcRPLY/rol+efLJ8UGjXGv2qdRNkBNeaLew==
|
||||
dependencies:
|
||||
hoist-non-react-statics "^2.5.0"
|
||||
prop-types "^15.6.1"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
react-native-tab-view "^1.0.0"
|
||||
|
||||
react-proxy@^1.1.7:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/react-proxy/-/react-proxy-1.1.8.tgz#9dbfd9d927528c3aa9f444e4558c37830ab8c26a"
|
||||
|
@ -94,7 +94,15 @@ export default function ScenesReducer(
|
||||
});
|
||||
|
||||
const nextKeys = new Set();
|
||||
nextState.routes.forEach((route, index) => {
|
||||
let nextRoutes = nextState.routes;
|
||||
if (nextRoutes.length > nextState.index + 1) {
|
||||
console.warn(
|
||||
'StackRouter provided invalid state, index should always be the top route'
|
||||
);
|
||||
nextRoutes = nextState.routes.slice(0, nextState.index + 1);
|
||||
}
|
||||
|
||||
nextRoutes.forEach((route, index) => {
|
||||
const key = SCENE_KEY_PREFIX + route.key;
|
||||
|
||||
let descriptor = descriptors && descriptors[route.key];
|
||||
@ -123,8 +131,15 @@ export default function ScenesReducer(
|
||||
});
|
||||
|
||||
if (prevState) {
|
||||
let prevRoutes = prevState.routes;
|
||||
if (prevRoutes.length > prevState.index + 1) {
|
||||
console.warn(
|
||||
'Stack provided invalid state, index should always be the top route'
|
||||
);
|
||||
prevRoutes = prevRoutes.slice(0, prevState.index + 1);
|
||||
}
|
||||
// Look at the previous routes and classify any removed scenes as `stale`.
|
||||
prevState.routes.forEach((route, index) => {
|
||||
prevRoutes.forEach((route, index) => {
|
||||
const key = SCENE_KEY_PREFIX + route.key;
|
||||
if (freshScenes.has(key)) {
|
||||
return;
|
||||
|
@ -11,8 +11,6 @@ const DefaultTransitionSpec = {
|
||||
timing: Animated.timing,
|
||||
};
|
||||
|
||||
const DEBUG = false;
|
||||
|
||||
class Transitioner extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
@ -69,19 +67,14 @@ class Transitioner extends React.Component {
|
||||
|
||||
// eslint-disable-next-line react/no-deprecated
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this._isTransitionRunning && !this._queuedTransition) {
|
||||
this._queuedTransition = { prevProps: this.props };
|
||||
if (this._isTransitionRunning) {
|
||||
if (!this._queuedTransition) {
|
||||
this._queuedTransition = { prevProps: this.props };
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let nextScenes = this._computeScenes(this.props, nextProps);
|
||||
|
||||
const indexHasChanged =
|
||||
nextProps.navigation.state.index !== this.props.navigation.state.index;
|
||||
|
||||
if (nextScenes) {
|
||||
this._startTransition(nextProps, nextScenes, indexHasChanged);
|
||||
}
|
||||
this._startTransition(this.props, nextProps);
|
||||
}
|
||||
|
||||
_computeScenes = (props, nextProps) => {
|
||||
@ -106,26 +99,27 @@ class Transitioner extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
if (__DEV__ && DEBUG) {
|
||||
console.log({ nextScenes: nextScenes.map(s => s.descriptor.key) });
|
||||
}
|
||||
|
||||
return nextScenes;
|
||||
};
|
||||
|
||||
_startTransition(nextProps, nextScenes, indexHasChanged) {
|
||||
_startTransition(props, nextProps) {
|
||||
const indexHasChanged =
|
||||
props.navigation.state.index !== nextProps.navigation.state.index;
|
||||
let nextScenes = this._computeScenes(props, nextProps);
|
||||
|
||||
if (!nextScenes) {
|
||||
// prevTransitionProps are the same as transitionProps in this case
|
||||
// because nothing changed
|
||||
this._prevTransitionProps = this._transitionProps;
|
||||
this._onTransitionEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
const nextState = {
|
||||
...this.state,
|
||||
scenes: nextScenes,
|
||||
};
|
||||
|
||||
if (__DEV__ && DEBUG) {
|
||||
console.log({
|
||||
startTransition: true,
|
||||
nextScenes: nextScenes.map(s => s.descriptor.key),
|
||||
});
|
||||
}
|
||||
|
||||
// grab the position animated value
|
||||
const { position } = nextState;
|
||||
|
||||
@ -135,7 +129,6 @@ class Transitioner extends React.Component {
|
||||
// compute transitionProps
|
||||
this._prevTransitionProps = this._transitionProps;
|
||||
this._transitionProps = buildTransitionProps(nextProps, nextState);
|
||||
|
||||
let { isTransitioning } = this._transitionProps.navigation.state;
|
||||
|
||||
// if the state isn't transitioning that is meant to signal that we should
|
||||
@ -205,17 +198,6 @@ class Transitioner extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (__DEV__ && DEBUG) {
|
||||
let key = this.props.navigation.state.key;
|
||||
let routeName = this.props.navigation.state.routeName;
|
||||
|
||||
console.log({
|
||||
render: true,
|
||||
[key]: this.state.scenes.map(d => d.key),
|
||||
route: routeName,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<View onLayout={this._onLayout} style={styles.main}>
|
||||
{this.props.render(this._transitionProps, this._prevTransitionProps)}
|
||||
@ -264,10 +246,6 @@ class Transitioner extends React.Component {
|
||||
scenes,
|
||||
};
|
||||
|
||||
if (__DEV__ && DEBUG) {
|
||||
console.log({ onTransitionEnd: true, scenes: scenes.map(s => s.key) });
|
||||
}
|
||||
|
||||
this._transitionProps = buildTransitionProps(this.props, nextState);
|
||||
|
||||
this.setState(nextState, async () => {
|
||||
@ -283,20 +261,9 @@ class Transitioner extends React.Component {
|
||||
}
|
||||
|
||||
if (this._queuedTransition) {
|
||||
const indexHasChanged =
|
||||
this.props.navigation.state.index !==
|
||||
this._queuedTransition.prevProps.navigation.state.index;
|
||||
let nextScenes = this._computeScenes(
|
||||
this._queuedTransition.prevProps,
|
||||
this.props
|
||||
);
|
||||
|
||||
if (nextScenes) {
|
||||
this._startTransition(this.props, nextScenes, indexHasChanged);
|
||||
} else {
|
||||
this._isTransitionRunning = false;
|
||||
}
|
||||
let { prevProps } = this._queuedTransition;
|
||||
this._queuedTransition = null;
|
||||
this._startTransition(prevProps, this.props);
|
||||
} else {
|
||||
this._isTransitionRunning = false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user