Compute scenes when queued transition starts

This commit is contained in:
Brent Vatne 2018-10-29 22:13:06 -07:00
parent 3be642e05a
commit 41af8e1451
2 changed files with 93 additions and 23 deletions

View File

@ -9,11 +9,24 @@ const Buttons = withNavigation(props => (
title="Go to Details" title="Go to Details"
onPress={() => props.navigation.navigate('Details')} onPress={() => props.navigation.navigate('Details')}
/> />
<Button title="Go and then go to details quick" onPress={() => {
let routeName = props.navigation.state.routeName;
props.navigation.pop();
setTimeout(() => {
props.navigation.navigate('Details');
}, 100);
}} />
<Button <Button
title="Go to Headerless" title="Go to Headerless"
onPress={() => props.navigation.navigate('Headerless')} onPress={() => props.navigation.navigate('Headerless')}
/> />
<Button title="Go back" onPress={() => props.navigation.goBack()} /> <Button title="Go back" onPress={() => props.navigation.goBack()} />
<Button title="Go back quick" onPress={() => {
props.navigation.pop();
setTimeout(() => {
props.navigation.pop();
}, 100);
}} />
<Button <Button
title="Go back to all examples" title="Go back to all examples"
onPress={() => props.navigation.navigate('Home')} onPress={() => props.navigation.navigate('Home')}
@ -26,6 +39,14 @@ class ListScreen extends React.Component {
title: 'List', title: 'List',
}; };
componentDidMount() {
console.log('ListScreen didMount');
}
componentWillUnmount() {
console.log('ListScreen willUnmount');
}
render() { render() {
return ( return (
<View <View
@ -52,6 +73,14 @@ class DetailsScreen extends React.Component {
}, },
}; };
componentDidMount() {
console.log('DetailsScreen didMount');
}
componentWillUnmount() {
console.log('DetailsScreen willUnmount');
}
render() { render() {
return ( return (
<View <View
@ -81,6 +110,14 @@ class HeaderlessScreen extends React.Component {
header: null, header: null,
}; };
componentDidMount() {
console.log('HeaderlessScreen didMount');
}
componentWillUnmount() {
console.log('HeaderlessScreen willUnmount');
}
render() { render() {
return ( return (
<View <View

View File

@ -68,22 +68,29 @@ class Transitioner extends React.Component {
// eslint-disable-next-line react/no-deprecated // eslint-disable-next-line react/no-deprecated
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (this._isTransitionRunning) {
this._queuedTransition = { nextProps, props: 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( let nextScenes = NavigationScenesReducer(
this.state.scenes, this.state.scenes,
nextProps.navigation.state, nextProps.navigation.state,
this.props.navigation.state, props.navigation.state,
nextProps.descriptors 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) { if (!nextProps.navigation.state.isTransitioning) {
nextScenes = filterStale(nextScenes); nextScenes = filterStale(nextScenes);
} }
@ -102,22 +109,31 @@ class Transitioner extends React.Component {
console.log({ nextScenes: nextScenes.map(s => s.descriptor.key) }); console.log({ nextScenes: nextScenes.map(s => s.descriptor.key) });
} }
const indexHasChanged = return nextScenes;
nextProps.navigation.state.index !== this.props.navigation.state.index; };
if (this._isTransitionRunning) {
this._queuedTransition = { nextProps, nextScenes, indexHasChanged };
return;
}
this._startTransition(nextProps, nextScenes, indexHasChanged);
}
_startTransition(nextProps, nextScenes, indexHasChanged) { _startTransition(nextProps, nextScenes, indexHasChanged) {
if (!nextScenes) {
console.log({
nextScenes,
scenes: this.state.scenes.map(s => s.descriptor.navigation.state.routeName),
state: nextProps.navigation.state.routes.length,
indexHasChanged,
})
nextScenes = this.state.scenes;
}
const nextState = { const nextState = {
...this.state, ...this.state,
scenes: nextScenes, scenes: nextScenes,
}; };
if (__DEV__ && DEBUG) {
console.log({
startTransition: true,
nextScenes: nextScenes.map(s => s.descriptor.key),
});
}
// grab the position animated value // grab the position animated value
const { position } = nextState; const { position } = nextState;
@ -199,7 +215,9 @@ class Transitioner extends React.Component {
if (__DEV__ && DEBUG) { if (__DEV__ && DEBUG) {
let key = this.props.navigation.state.key; let key = this.props.navigation.state.key;
let routeName = this.props.navigation.state.routeName; let routeName = this.props.navigation.state.routeName;
console.log({ console.log({
render: true,
[key]: this.state.scenes.map(d => d.key), [key]: this.state.scenes.map(d => d.key),
route: routeName, route: routeName,
}); });
@ -253,6 +271,10 @@ class Transitioner extends React.Component {
scenes, scenes,
}; };
if (__DEV__ && DEBUG) {
console.log({ onTransitionEnd: true, scenes: scenes.map(s => s.key) });
}
this._transitionProps = buildTransitionProps(this.props, nextState); this._transitionProps = buildTransitionProps(this.props, nextState);
this.setState(nextState, async () => { this.setState(nextState, async () => {
@ -268,12 +290,23 @@ class Transitioner extends React.Component {
} }
if (this._queuedTransition) { if (this._queuedTransition) {
const indexHasChanged =
this._queuedTransition.nextProps.navigation.state.index !==
this._queuedTransition.props.navigation.state.index;
let nextScenes = this._computeScenes(
this._queuedTransition.props,
this._queuedTransition.nextProps
);
if (nextScenes) {
this._startTransition( this._startTransition(
this._queuedTransition.nextProps, this._queuedTransition.nextProps,
this._queuedTransition.nextScenes, nextScenes,
this._queuedTransition.indexHasChanged indexHasChanged
); );
}
this._queuedTransition = null; this._queuedTransition = null;
this._isTransitionRunning = false;
} else { } else {
this._isTransitionRunning = false; this._isTransitionRunning = false;
} }