Skip to content

Instantly share code, notes, and snippets.

@guimello
Forked from reu/collapsable.js
Last active April 25, 2017 21:17
Show Gist options
  • Save guimello/32c988bb02db8eac32f0dcdf06629291 to your computer and use it in GitHub Desktop.
Save guimello/32c988bb02db8eac32f0dcdf06629291 to your computer and use it in GitHub Desktop.
import React, {
Component,
PropTypes,
} from "react";
import {
Animated,
View,
} from "react-native";
export default class Collapsable extends Component {
static propTypes = {
children: PropTypes.node,
collapsed: PropTypes.bool,
};
state = {
animation: new Animated.Value(0),
firstRender: true,
};
close({ duration = 200 } = {}) {
Animated.timing(this.state.animation, {
toValue: 0,
duration,
}).start(() => this.setState({ collapsed: true }));
}
open({ duration = 200 } = {}) {
Animated.timing(this.state.animation, {
toValue: this.state.height,
duration,
}).start(() => this.setState({ collapsed: false }));
}
componentDidMount() {
this.props.collapsed ? this.close() : this.open();
}
componentWillReceiveProps(nextProps) {
const shouldCollapse = nextProps.collapsed;
if (this.state.collapsed != shouldCollapse) {
shouldCollapse ? this.close() : this.open();
}
}
render() {
const height = this.state.firstRender ? null : this.state.animation;
return (
<Animated.View style={{ height, overflow: "hidden" }}>
<View onLayout={this.wrapperOnLayout.bind(this)}>
{this.props.children}
</View>
</Animated.View>
);
}
wrapperOnLayout(event) {
if (this.state.firstRender) {
const height = event.nativeEvent.layout.height;
this.state.animation.setValue(height);
this.setState({ height, firstRender: false }, () => {
this.props.collapsed ? this.close({ duration: 0 }) : this.open({ duration: 0 });
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment