[RN] Refactor SideBar layout and animation (coding style)

This commit is contained in:
Lyubo Marinov 2018-06-01 14:53:46 -05:00
parent c700261852
commit c6d553738f
2 changed files with 41 additions and 47 deletions

View File

@ -1,11 +1,7 @@
// @flow
import React, { Component, type Node } from 'react';
import {
Animated,
TouchableWithoutFeedback,
View
} from 'react-native';
import { Animated, TouchableWithoutFeedback, View } from 'react-native';
import styles, { SIDEBAR_WIDTH } from './styles';
@ -15,21 +11,21 @@ import styles, { SIDEBAR_WIDTH } from './styles';
type Props = {
/**
* The children of the Component
* The children of {@code SideBar}.
*/
children: Node,
/**
* Callback to notify the containing Component that the sidebar is
* Callback to notify the containing {@code Component} that the sidebar is
* closing.
*/
onHide: Function,
/**
* Sets the menu displayed or hidden.
* Whether the menu (of the {@code SideBar}?) is displayed/rendered/shown.
*/
show: boolean
}
};
/**
* The type of the React {@code Component} state of {@link SideBar}.
@ -37,18 +33,18 @@ type Props = {
type State = {
/**
* Indicates whether the side overlay should be rendered or not.
* Whether the side overlay should be displayed/rendered/shown.
*/
showOverlay: boolean,
/**
* The native animation object.
*/
sliderAnimation: Object
}
sliderAnimation: Animated.Value
};
/**
* A generic animated side bar to be used for left side menus
* A generic animated side bar to be used for left-side, hamburger-style menus.
*/
export default class SideBar extends Component<Props, State> {
/**
@ -64,11 +60,12 @@ export default class SideBar extends Component<Props, State> {
sliderAnimation: new Animated.Value(0)
};
// Bind event handlers so they are only bound once per instance.
this._onHideMenu = this._onHideMenu.bind(this);
}
/**
* Implements the Component's componentDidMount method.
* Implements React's {@link Component#componentDidMount()}.
*
* @inheritdoc
*/
@ -77,14 +74,12 @@ export default class SideBar extends Component<Props, State> {
}
/**
* Implements the Component's componentWillReceiveProps method.
* Implements React's {@link Component#componentWillReceiveProps()}.
*
* @inheritdoc
*/
componentWillReceiveProps(newProps: Props) {
if (newProps.show !== this.props.show) {
this._setShow(newProps.show);
}
componentWillReceiveProps({ show }: Props) {
(show === this.props.show) || this._setShow(show);
}
/**
@ -120,17 +115,16 @@ export default class SideBar extends Component<Props, State> {
* @returns {Array<Object>}
*/
_getContentStyle() {
const { sliderAnimation } = this.state;
const transformStyle
= { transform: [ { translateX: sliderAnimation } ] };
return [ styles.sideMenuContent, transformStyle ];
return [
styles.sideMenuContent,
{ transform: [ { translateX: this.state.sliderAnimation } ] }
];
}
_onHideMenu: () => void;
/**
* Hides the menu.
* Hides the side menu.
*
* @private
* @returns {void}
@ -146,28 +140,30 @@ export default class SideBar extends Component<Props, State> {
_setShow: (boolean) => void;
/**
* Sets the side menu visible or hidden.
* Shows/hides the side menu.
*
* @param {boolean} show - The new expected visibility value.
* @param {boolean} show - If the side menu is to be made visible,
* {@code true}; otherwise, {@code false}.
* @private
* @returns {void}
*/
_setShow(show) {
if (show) {
this.setState({ showOverlay: true });
}
show && this.setState({ showOverlay: true });
Animated
.timing(
this.state.sliderAnimation,
{
/* value */ this.state.sliderAnimation,
/* config */ {
toValue: show ? SIDEBAR_WIDTH : 0,
useNativeDriver: true
})
.start(animationState => {
if (animationState.finished && !show) {
this.setState({ showOverlay: false });
}
.start(({ finished }) => {
finished && !show && this.setState({ showOverlay: false });
// XXX Technically, the arrow function can further be simplified
// by removing the {} and returning the boolean expression
// above. Practically and unfortunately though, Flow freaks out
// and states that Animated.timing doesn't exist!?
});
}
}

View File

@ -1,10 +1,8 @@
// @flow
import { StyleSheet } from 'react-native';
import {
BoxModel,
ColorPalette,
createStyleSheet
} from '../../../styles';
import { BoxModel, ColorPalette, createStyleSheet } from '../../../styles';
const AVATAR_OPACITY = 0.4;
const AVATAR_SIZE = 65;
@ -21,7 +19,7 @@ export const UNDERLAY_COLOR = 'rgba(255, 255, 255, 0.2)';
const HEADER_STYLES = {
/**
* Platform specific header button (e.g. back, menu...etc).
* Platform specific header button (e.g. back, menu, etc).
*/
headerButton: {
alignSelf: 'center',
@ -57,7 +55,7 @@ const HEADER_STYLES = {
},
/**
* Base style of Header
* Base style of Header.
*/
screenHeader: {
alignItems: 'center',
@ -293,8 +291,8 @@ const SIDEBAR_STYLES = {
},
/**
* The opaque area that covers the rest of the screen, when
* the side bar is open.
* The opaque area that covers the rest of the screen, when the side bar is
* open.
*/
sideMenuShadow: {
...StyleSheet.absoluteFillObject,
@ -303,8 +301,8 @@ const SIDEBAR_STYLES = {
};
/**
* The styles of the React {@code Components} of the generic components
* in the app.
* The styles of the generic React {@code Component}s implemented by the feature
* base/react.
*/
export default createStyleSheet({
...HEADER_STYLES,