Merge pull request #49 from react-navigation/@brent/queued-transitions
Rethink queued transitions
This commit is contained in:
commit
61a8f2253b
|
@ -9,11 +9,29 @@ const Buttons = withNavigation(props => (
|
|||
title="Go to Details"
|
||||
onPress={() => props.navigation.navigate('Details')}
|
||||
/>
|
||||
<Button
|
||||
title="Go and then go to details quick"
|
||||
onPress={() => {
|
||||
props.navigation.pop();
|
||||
setTimeout(() => {
|
||||
props.navigation.navigate('Details');
|
||||
}, 100);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
title="Go to Headerless"
|
||||
onPress={() => props.navigation.navigate('Headerless')}
|
||||
/>
|
||||
<Button title="Go back" onPress={() => props.navigation.goBack()} />
|
||||
<Button
|
||||
title="Go back quick"
|
||||
onPress={() => {
|
||||
props.navigation.pop();
|
||||
setTimeout(() => {
|
||||
props.navigation.pop();
|
||||
}, 100);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
title="Go back to all examples"
|
||||
onPress={() => props.navigation.navigate('Home')}
|
||||
|
@ -26,6 +44,14 @@ class ListScreen extends React.Component {
|
|||
title: 'List',
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
console.log('ListScreen didMount');
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
console.log('ListScreen willUnmount');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View
|
||||
|
@ -52,6 +78,14 @@ class DetailsScreen extends React.Component {
|
|||
},
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
console.log('DetailsScreen didMount');
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
console.log('DetailsScreen willUnmount');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View
|
||||
|
@ -81,6 +115,14 @@ class HeaderlessScreen extends React.Component {
|
|||
header: null,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
console.log('HeaderlessScreen didMount');
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
console.log('HeaderlessScreen willUnmount');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View
|
||||
|
|
|
@ -51,6 +51,7 @@ class Transitioner extends React.Component {
|
|||
|
||||
this._prevTransitionProps = null;
|
||||
this._transitionProps = buildTransitionProps(props, this.state);
|
||||
|
||||
this._isMounted = false;
|
||||
this._isTransitionRunning = false;
|
||||
this._queuedTransition = null;
|
||||
|
@ -68,22 +69,29 @@ class Transitioner extends React.Component {
|
|||
|
||||
// eslint-disable-next-line react/no-deprecated
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this._isTransitionRunning && !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);
|
||||
}
|
||||
}
|
||||
|
||||
_computeScenes = (props, nextProps) => {
|
||||
let nextScenes = NavigationScenesReducer(
|
||||
this.state.scenes,
|
||||
nextProps.navigation.state,
|
||||
this.props.navigation.state,
|
||||
props.navigation.state,
|
||||
nextProps.descriptors
|
||||
);
|
||||
|
||||
// We are adding one or more scene! We can't handle a case where the number
|
||||
// of scenes increases and one or more of the new scenes is not in the
|
||||
// current navigation state, so we filter anything that's not in the
|
||||
// navigation state right now out and assume it has been transitioned out
|
||||
// properly beforehand.
|
||||
if (nextScenes.length > this.state.scenes.length) {
|
||||
nextScenes = filterNotInState(nextScenes, nextProps.navigation.state);
|
||||
}
|
||||
|
||||
if (!nextProps.navigation.state.isTransitioning) {
|
||||
nextScenes = filterStale(nextScenes);
|
||||
}
|
||||
|
@ -102,15 +110,8 @@ class Transitioner extends React.Component {
|
|||
console.log({ nextScenes: nextScenes.map(s => s.descriptor.key) });
|
||||
}
|
||||
|
||||
const indexHasChanged =
|
||||
nextProps.navigation.state.index !== this.props.navigation.state.index;
|
||||
if (this._isTransitionRunning) {
|
||||
this._queuedTransition = { nextProps, nextScenes, indexHasChanged };
|
||||
return;
|
||||
}
|
||||
|
||||
this._startTransition(nextProps, nextScenes, indexHasChanged);
|
||||
}
|
||||
return nextScenes;
|
||||
};
|
||||
|
||||
_startTransition(nextProps, nextScenes, indexHasChanged) {
|
||||
const nextState = {
|
||||
|
@ -118,6 +119,13 @@ class Transitioner extends React.Component {
|
|||
scenes: nextScenes,
|
||||
};
|
||||
|
||||
if (__DEV__ && DEBUG) {
|
||||
console.log({
|
||||
startTransition: true,
|
||||
nextScenes: nextScenes.map(s => s.descriptor.key),
|
||||
});
|
||||
}
|
||||
|
||||
// grab the position animated value
|
||||
const { position } = nextState;
|
||||
|
||||
|
@ -127,6 +135,7 @@ 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
|
||||
|
@ -199,7 +208,9 @@ class Transitioner extends React.Component {
|
|||
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,
|
||||
});
|
||||
|
@ -253,6 +264,10 @@ 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 () => {
|
||||
|
@ -268,11 +283,19 @@ class Transitioner extends React.Component {
|
|||
}
|
||||
|
||||
if (this._queuedTransition) {
|
||||
this._startTransition(
|
||||
this._queuedTransition.nextProps,
|
||||
this._queuedTransition.nextScenes,
|
||||
this._queuedTransition.indexHasChanged
|
||||
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;
|
||||
}
|
||||
this._queuedTransition = null;
|
||||
} else {
|
||||
this._isTransitionRunning = false;
|
||||
|
@ -313,26 +336,6 @@ function filterStale(scenes) {
|
|||
return filtered;
|
||||
}
|
||||
|
||||
function filterNotInState(scenes, state) {
|
||||
let activeKeys = state.routes.map(r => r.key);
|
||||
let filtered = scenes.filter(scene =>
|
||||
activeKeys.includes(scene.descriptor.key)
|
||||
);
|
||||
|
||||
if (__DEV__ && DEBUG) {
|
||||
console.log({
|
||||
activeKeys,
|
||||
filtered: filtered.map(s => s.descriptor.key),
|
||||
scenes: scenes.map(s => s.descriptor.key),
|
||||
});
|
||||
}
|
||||
|
||||
if (filtered.length === scenes.length) {
|
||||
return scenes;
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
function isSceneActive(scene) {
|
||||
return scene.isActive;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue