mirror of
https://github.com/status-im/react-native.git
synced 2025-02-26 16:10:58 +00:00
Clean up NavigationAnimatedView
Summary:- Add flow type checks. - Fix code styles. - Improve the logics to update `this.state.scenes`. - Improve the logics to pass the layout. Reviewed By: ericvicenti Differential Revision: D3022107 fb-gh-sync-id: 23f4ed22db797f68bde0ba4f3cdd123701934fc3 shipit-source-id: 23f4ed22db797f68bde0ba4f3cdd123701934fc3
This commit is contained in:
parent
e76fb68141
commit
b5ae8a8ece
@ -21,9 +21,11 @@ const View = require('View');
|
||||
import type {
|
||||
NavigationAnimatedValue,
|
||||
NavigationAnimationSetter,
|
||||
NavigationLayout,
|
||||
NavigationParentState,
|
||||
NavigationScene,
|
||||
NavigationSceneRenderer,
|
||||
NavigationState,
|
||||
} from 'NavigationTypeDefinition';
|
||||
|
||||
/**
|
||||
@ -102,71 +104,87 @@ const defaultProps = {
|
||||
class NavigationAnimatedView
|
||||
extends React.Component<any, Props, State> {
|
||||
|
||||
_animatedHeight: Animated.Value;
|
||||
_animatedWidth: Animated.Value;
|
||||
_lastHeight: number;
|
||||
_lastWidth: number;
|
||||
_layout: NavigationLayout;
|
||||
_onLayout: (event: any) => void;
|
||||
_onProgressChange: (data: {value: number}) => void;
|
||||
_positionListener: any;
|
||||
|
||||
props: Props;
|
||||
state: State;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this._lastWidth = 0;
|
||||
this._lastHeight = 0;
|
||||
this._animatedHeight = new Animated.Value(this._lastHeight);
|
||||
this._animatedWidth = new Animated.Value(this._lastWidth);
|
||||
constructor(props: Props, context: any) {
|
||||
super(props, context);
|
||||
|
||||
this._layout = {
|
||||
initWidth: 0,
|
||||
initHeight: 0,
|
||||
width: new Animated.Value(0),
|
||||
height: new Animated.Value(0),
|
||||
};
|
||||
|
||||
this.state = {
|
||||
position: new Animated.Value(this.props.navigationState.index),
|
||||
scenes: [],
|
||||
scenes: this._reduceScenes([], this.props.navigationState),
|
||||
};
|
||||
}
|
||||
componentWillMount() {
|
||||
this.setState({
|
||||
scenes: this._reduceScenes(this.state.scenes, this.props.navigationState),
|
||||
});
|
||||
|
||||
componentWillMount(): void {
|
||||
this._onLayout = this._onLayout.bind(this);
|
||||
this._onProgressChange = this._onProgressChange.bind(this);
|
||||
}
|
||||
componentDidMount() {
|
||||
this._positionListener = this.state.position.addListener(this._onProgressChange.bind(this));
|
||||
|
||||
componentDidMount(): void {
|
||||
this._positionListener =
|
||||
this.state.position.addListener(this._onProgressChange);
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
|
||||
componentWillReceiveProps(nextProps: Props): void {
|
||||
if (nextProps.navigationState !== this.props.navigationState) {
|
||||
this.setState({
|
||||
scenes: this._reduceScenes(this.state.scenes, nextProps.navigationState, this.props.navigationState),
|
||||
scenes: this._reduceScenes(
|
||||
this.state.scenes,
|
||||
nextProps.navigationState,
|
||||
this.props.navigationState
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
componentDidUpdate(lastProps) {
|
||||
if (lastProps.navigationState.index !== this.props.navigationState.index && this.props.setTiming) {
|
||||
this.props.setTiming(this.state.position, this.props.navigationState, lastProps.navigationState);
|
||||
|
||||
componentDidUpdate(lastProps: Props): void {
|
||||
if (lastProps.navigationState.index !== this.props.navigationState.index) {
|
||||
this.props.setTiming(
|
||||
this.state.position,
|
||||
this.props.navigationState,
|
||||
lastProps.navigationState
|
||||
);
|
||||
}
|
||||
}
|
||||
componentWillUnmount() {
|
||||
if (this._positionListener) {
|
||||
this.state.position.removeListener(this._positionListener);
|
||||
this._positionListener = null;
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
this.state.position.removeListener(this._positionListener);
|
||||
}
|
||||
|
||||
_onProgressChange(data: Object): void {
|
||||
if (Math.abs(data.value - this.props.navigationState.index) > Number.EPSILON) {
|
||||
const delta = Math.abs(data.value - this.props.navigationState.index);
|
||||
if (delta > Number.EPSILON) {
|
||||
return;
|
||||
}
|
||||
this.state.scenes.forEach((scene, index) => {
|
||||
if (scene.isStale) {
|
||||
const scenes = this.state.scenes.slice();
|
||||
scenes.splice(index, 1);
|
||||
this.setState({ scenes, });
|
||||
}
|
||||
|
||||
const scenes = this.state.scenes.filter(scene => {
|
||||
return !scene.isStale;
|
||||
});
|
||||
|
||||
if (scenes.length !== this.state.scenes.length) {
|
||||
this.setState({ scenes });
|
||||
}
|
||||
}
|
||||
|
||||
_reduceScenes(
|
||||
scenes: Array<NavigationScene>,
|
||||
nextState: NavigationParentState,
|
||||
lastState: ?NavigationParentState
|
||||
): Array<NavigationScene> {
|
||||
let nextScenes = nextState.children.map((child, index) => {
|
||||
const nextScenes = nextState.children.map((child, index) => {
|
||||
return {
|
||||
index,
|
||||
isStale: false,
|
||||
@ -175,8 +193,11 @@ class NavigationAnimatedView
|
||||
});
|
||||
|
||||
if (lastState) {
|
||||
lastState.children.forEach((child, index) => {
|
||||
if (!NavigationStateUtils.get(nextState, child.key) && index !== nextState.index) {
|
||||
lastState.children.forEach((child: NavigationState, index: number) => {
|
||||
if (
|
||||
!NavigationStateUtils.get(nextState, child.key) &&
|
||||
index !== nextState.index
|
||||
) {
|
||||
nextScenes.push({
|
||||
index,
|
||||
isStale: true,
|
||||
@ -186,38 +207,21 @@ class NavigationAnimatedView
|
||||
});
|
||||
}
|
||||
|
||||
nextScenes = nextScenes.sort(compareScenes);
|
||||
|
||||
return nextScenes;
|
||||
return nextScenes.sort(compareScenes);
|
||||
}
|
||||
render() {
|
||||
|
||||
render(): ReactElement {
|
||||
return (
|
||||
<View
|
||||
onLayout={(e) => {
|
||||
const {height, width} = e.nativeEvent.layout;
|
||||
this._animatedHeight &&
|
||||
this._animatedHeight.setValue(height);
|
||||
this._animatedWidth &&
|
||||
this._animatedWidth.setValue(width);
|
||||
this._lastHeight = height;
|
||||
this._lastWidth = width;
|
||||
}}
|
||||
onLayout={this._onLayout}
|
||||
style={this.props.style}>
|
||||
{this.state.scenes.map(this._renderScene, this)}
|
||||
{this._renderOverlay()}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
_getLayout() {
|
||||
return {
|
||||
height: this._animatedHeight,
|
||||
width: this._animatedWidth,
|
||||
initWidth: this._lastWidth,
|
||||
initHeight: this._lastHeight,
|
||||
};
|
||||
}
|
||||
|
||||
_renderScene(scene: NavigationScene) {
|
||||
_renderScene(scene: NavigationScene): ?ReactElement {
|
||||
const {
|
||||
navigationState,
|
||||
onNavigate,
|
||||
@ -230,7 +234,7 @@ class NavigationAnimatedView
|
||||
} = this.state;
|
||||
|
||||
return renderScene({
|
||||
layout: this._getLayout(),
|
||||
layout: this._layout,
|
||||
navigationState,
|
||||
onNavigate,
|
||||
position,
|
||||
@ -239,7 +243,7 @@ class NavigationAnimatedView
|
||||
});
|
||||
}
|
||||
|
||||
_renderOverlay() {
|
||||
_renderOverlay(): ?ReactElement {
|
||||
if (this.props.renderOverlay) {
|
||||
const {
|
||||
navigationState,
|
||||
@ -253,7 +257,7 @@ class NavigationAnimatedView
|
||||
} = this.state;
|
||||
|
||||
return renderOverlay({
|
||||
layout: this._getLayout(),
|
||||
layout: this._layout,
|
||||
navigationState,
|
||||
onNavigate,
|
||||
position,
|
||||
@ -263,6 +267,21 @@ class NavigationAnimatedView
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_onLayout(event: any): void {
|
||||
const {height, width} = event.nativeEvent.layout;
|
||||
|
||||
const layout = {
|
||||
...this._layout,
|
||||
initHeight: height,
|
||||
initWidth: width,
|
||||
};
|
||||
|
||||
this._layout = layout;
|
||||
|
||||
layout.height.setValue(height);
|
||||
layout.width.setValue(width);
|
||||
}
|
||||
}
|
||||
|
||||
NavigationAnimatedView.propTypes = propTypes;
|
||||
|
Loading…
x
Reference in New Issue
Block a user