diff --git a/ActionButton.js b/ActionButton.js
index ec1b9e3..65566ea 100644
--- a/ActionButton.js
+++ b/ActionButton.js
@@ -1,11 +1,11 @@
-import React, { Component, useState, useRef, useEffect } from "react";
+import React, { Component } from "react";
import PropTypes from "prop-types";
import {
StyleSheet,
Text,
View,
Animated,
- TouchableOpacity
+ TouchableOpacity,
} from "react-native";
import ActionButtonItem from "./ActionButtonItem";
import {
@@ -17,160 +17,222 @@ import {
DEFAULT_ACTIVE_OPACITY
} from "./shared";
-const ActionButton = props => {
- const [, setResetToken] = useState(props.resetToken);
- const [active, setActive] = useState(props.active);
- const anim = useRef(new Animated.Value(props.active ? 1 : 0));
- const timeout = useRef(null);
- const mounted = useRef(false);
+export default class ActionButton extends Component {
+ constructor(props) {
+ super(props);
- useEffect(() => {
- mounted.current = true;
-
- return () => {
- mounted.current = false;
- timeout.current && clearTimeout(timeout.current);
+ this.state = {
+ resetToken: props.resetToken,
+ active: props.active
};
- }, []);
- useEffect(() => {
- if (props.active) {
- Animated.spring(anim.current, { toValue: 1 }).start();
- setActive(true);
- setResetToken(props.resetToken);
- } else {
- props.onReset && props.onReset();
+ this.anim = new Animated.Value(props.active ? 1 : 0);
+ this.timeout = null;
+ }
+
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ clearTimeout(this.timeout);
+ }
- Animated.spring(anim.current, { toValue: 0 }).start();
- timeout.current = setTimeout(() => {
- setActive(false);
- setResetToken(props.resetToken);
- }, 250);
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.resetToken !== this.state.resetToken) {
+ if (nextProps.active === false && this.state.active === true) {
+ if (this.props.onReset) this.props.onReset();
+ Animated.spring(this.anim, { toValue: 0, useNativeDriver: false }).start();
+ setTimeout(
+ () =>
+ this.setState({ active: false, resetToken: nextProps.resetToken }),
+ 250
+ );
+ return;
+ }
+
+ if (nextProps.active === true && this.state.active === false) {
+ Animated.spring(this.anim, { toValue: 1, useNativeDriver: false }).start();
+ this.setState({ active: true, resetToken: nextProps.resetToken });
+ return;
+ }
+
+ this.setState({
+ resetToken: nextProps.resetToken,
+ active: nextProps.active
+ });
}
- }, [props.resetToken, props.active]);
+ }
//////////////////////
// STYLESHEET GETTERS
//////////////////////
- const getOrientation = () => {
- return { alignItems: alignItemsMap[props.position] };
- };
+ getOrientation() {
+ return { alignItems: alignItemsMap[this.props.position] };
+ }
- const getOffsetXY = () => {
+ getOffsetXY() {
return {
- // paddingHorizontal: props.offsetX,
- paddingVertical: props.offsetY
+ // paddingHorizontal: this.props.offsetX,
+ paddingVertical: this.props.offsetY
};
- };
+ }
- const getOverlayStyles = () => {
+ getOverlayStyles() {
return [
styles.overlay,
{
- elevation: props.elevation,
- zIndex: props.zIndex,
- justifyContent:
- props.verticalOrientation === "up" ? "flex-end" : "flex-start"
+ elevation: this.props.elevation,
+ zIndex: this.props.zIndex,
+ justifyContent: this.props.verticalOrientation === "up"
+ ? "flex-end"
+ : "flex-start"
}
];
- };
+ }
+
+ //////////////////////
+ // RENDER METHODS
+ //////////////////////
+
+ render() {
+ return (
+
+
+ {this.props.backdrop}
+
+
+ {this.state.active &&
+ !this.props.backgroundTappable &&
+ this._renderTappableBackground()}
+
+ {this.props.verticalOrientation === "up" &&
+ this.props.children &&
+ this._renderActions()}
+ {this._renderMainButton()}
+ {this.props.verticalOrientation === "down" &&
+ this.props.children &&
+ this._renderActions()}
+
+
+ );
+ }
- const _renderMainButton = () => {
+ _renderMainButton() {
const animatedViewStyle = {
transform: [
{
- scale: anim.current.interpolate({
+ scale: this.anim.interpolate({
inputRange: [0, 1],
- outputRange: [1, props.outRangeScale]
+ outputRange: [1, this.props.outRangeScale]
})
},
{
- rotate: anim.current.interpolate({
+ rotate: this.anim.interpolate({
inputRange: [0, 1],
- outputRange: ["0deg", props.degrees + "deg"]
+ outputRange: ["0deg", this.props.degrees + "deg"]
})
}
]
};
const wrapperStyle = {
- backgroundColor: anim.current.interpolate({
+ backgroundColor: this.anim.interpolate({
inputRange: [0, 1],
- outputRange: [props.buttonColor, props.btnOutRange || props.buttonColor]
+ outputRange: [
+ this.props.buttonColor,
+ this.props.btnOutRange || this.props.buttonColor
+ ]
}),
- width: props.size,
- height: props.size,
- borderRadius: props.size / 2
+ width: this.props.size,
+ height: this.props.size,
+ borderRadius: this.props.size / 2
};
const buttonStyle = {
- width: props.size,
- height: props.size,
- borderRadius: props.size / 2,
+ width: this.props.size,
+ height: this.props.size,
+ borderRadius: this.props.size / 2,
alignItems: "center",
justifyContent: "center"
};
- const Touchable = getTouchableComponent(props.useNativeFeedback);
- const parentStyle =
- isAndroid && props.fixNativeFeedbackRadius
- ? {
- right: props.offsetX,
- zIndex: props.zIndex,
- borderRadius: props.size / 2,
- width: props.size
- }
- : { marginHorizontal: props.offsetX, zIndex: props.zIndex };
+ const Touchable = getTouchableComponent(this.props.useNativeFeedback);
+ const parentStyle = isAndroid &&
+ this.props.fixNativeFeedbackRadius
+ ? {
+ right: this.props.offsetX,
+ zIndex: this.props.zIndex,
+ borderRadius: this.props.size / 2,
+ width: this.props.size
+ }
+ : { marginHorizontal: this.props.offsetX, zIndex: this.props.zIndex };
return (
-
{
- props.onPress();
- if (props.children) animateButton();
+ this.props.onPress();
+ if (this.props.children) this.animateButton();
}}
- onPressIn={props.onPressIn}
- onPressOut={props.onPressOut}
+ onPressIn={this.props.onPressIn}
+ onPressOut={this.props.onPressOut}
>
-
+
- {_renderButtonIcon()}
+ {this._renderButtonIcon()}
);
- };
-
- const _renderButtonIcon = () => {
- const {
- icon,
- renderIcon,
- btnOutRangeTxt,
- buttonTextStyle,
- buttonText
- } = props;
- if (renderIcon) return renderIcon(active);
+ }
+
+ _renderButtonIcon() {
+ const { icon, renderIcon, btnOutRangeTxt, buttonTextStyle, buttonText } = this.props;
+ if (renderIcon) return renderIcon(this.state.active);
if (icon) {
- console.warn(
- "react-native-action-button: The `icon` prop is deprecated! Use `renderIcon` instead."
- );
+ console.warn('react-native-action-button: The `icon` prop is deprecated! Use `renderIcon` instead.');
return icon;
}
@@ -182,7 +244,7 @@ const ActionButton = props => {
styles.btnText,
buttonTextStyle,
{
- color: anim.current.interpolate({
+ color: this.anim.interpolate({
inputRange: [0, 1],
outputRange: [textColor, btnOutRangeTxt || textColor]
})
@@ -192,26 +254,26 @@ const ActionButton = props => {
{buttonText}
);
- };
+ }
- const _renderActions = () => {
- const { children, verticalOrientation } = props;
+ _renderActions() {
+ const { children, verticalOrientation } = this.props;
- if (!active) return null;
+ if (!this.state.active) return null;
let actionButtons = !Array.isArray(children) ? [children] : children;
- actionButtons = actionButtons.filter(
- actionButton => typeof actionButton == "object"
- );
+ actionButtons = actionButtons.filter( actionButton => (typeof actionButton == 'object') )
const actionStyle = {
flex: 1,
alignSelf: "stretch",
// backgroundColor: 'purple',
justifyContent: verticalOrientation === "up" ? "flex-end" : "flex-start",
- paddingTop: props.verticalOrientation === "down" ? props.spacing : 0,
- zIndex: props.zIndex
+ paddingTop: this.props.verticalOrientation === "down"
+ ? this.props.spacing
+ : 0,
+ zIndex: this.props.zIndex
};
return (
@@ -219,14 +281,14 @@ const ActionButton = props => {
{actionButtons.map((ActionButton, idx) => (
{
- if (props.autoInactive) {
- timeout.current = setTimeout(reset, 200);
+ if (this.props.autoInactive) {
+ this.timeout = setTimeout(this.reset.bind(this), 200);
}
ActionButton.props.onPress();
}}
@@ -234,84 +296,50 @@ const ActionButton = props => {
))}
);
- };
+ }
- const _renderTappableBackground = () => {
+ _renderTappableBackground() {
return (
);
- };
+ }
//////////////////////
// Animation Methods
//////////////////////
- const animateButton = (animate = true) => {
- if (active) return reset(animate);
+ animateButton(animate = true) {
+ if (this.state.active) return this.reset();
if (animate) {
- Animated.spring(anim.current, { toValue: 1 }).start();
+ Animated.spring(this.anim, { toValue: 1, useNativeDriver: false }).start();
} else {
- anim.current.setValue(1);
+ this.anim.setValue(1);
}
- setActive(true);
- };
+ this.setState({ active: true, resetToken: this.state.resetToken });
+ }
- const reset = (animate = true) => {
- if (props.onReset) props.onReset();
+ reset(animate = true) {
+ if (this.props.onReset) this.props.onReset();
if (animate) {
- Animated.spring(anim.current, { toValue: 0 }).start();
+ Animated.spring(this.anim, { toValue: 0, useNativeDriver: false }).start();
} else {
- anim.current.setValue(0);
+ this.anim.setValue(0);
}
- timeout.current = setTimeout(() => {
- if (mounted.current) {
- setActive(false);
+ setTimeout(() => {
+ if (this.mounted) {
+ this.setState({ active: false, resetToken: this.state.resetToken });
}
}, 250);
- };
-
- return (
-
-
- {props.backdrop}
-
-
- {active && !props.backgroundTappable && _renderTappableBackground()}
-
- {props.verticalOrientation === "up" &&
- props.children &&
- _renderActions()}
- {_renderMainButton()}
- {props.verticalOrientation === "down" &&
- props.children &&
- _renderActions()}
-
-
- );
-};
+ }
+}
ActionButton.Item = ActionButtonItem;
@@ -407,4 +435,3 @@ const styles = StyleSheet.create({
backgroundColor: "transparent"
}
});
-export default ActionButton;