From 3c03184b318b4e9dc9936c7c33823e8be17a70d7 Mon Sep 17 00:00:00 2001 From: Marc Glasser Date: Wed, 19 Jul 2023 15:53:14 -1000 Subject: [PATCH 1/4] Refactor FloatingActionButton --- src/components/FloatingActionButton.js | 116 ++++++++++++------------- 1 file changed, 57 insertions(+), 59 deletions(-) diff --git a/src/components/FloatingActionButton.js b/src/components/FloatingActionButton.js index 706bad59f7b7..c2b1b98700e1 100644 --- a/src/components/FloatingActionButton.js +++ b/src/components/FloatingActionButton.js @@ -1,4 +1,4 @@ -import React, {PureComponent} from 'react'; +import React, {useCallback, useEffect, useRef} from 'react'; import {Animated, Easing, View} from 'react-native'; import PropTypes from 'prop-types'; import Icon from './Icon'; @@ -9,6 +9,7 @@ import themeColors from '../styles/themes/default'; import Tooltip from './Tooltip'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import PressableWithFeedback from './Pressable/PressableWithFeedback'; +import usePrevious from '../hooks/usePrevious'; const AnimatedIcon = Animated.createAnimatedComponent(Icon); AnimatedIcon.displayName = 'AnimatedIcon'; @@ -26,78 +27,75 @@ const propTypes = { ...withLocalizePropTypes, }; -class FloatingActionButton extends PureComponent { - constructor(props) { - super(props); - this.animatedValue = new Animated.Value(props.isActive ? 1 : 0); - } - - componentDidUpdate(prevProps) { - if (prevProps.isActive === this.props.isActive) { - return; - } - - this.animateFloatingActionButton(); - } +function FloatingActionButton({isActive, onPress, translate, accessibilityLabel, accessibilityRole}) { + const prevIsActive = usePrevious(isActive); + const animatedValue = useRef(new Animated.Value(isActive ? 1 : 0)); + const fabPressable = useRef(null); /** * Animates the floating action button * Method is called when the isActive prop changes */ - animateFloatingActionButton() { - const animationFinalValue = this.props.isActive ? 1 : 0; + const animateFloatingActionButton = useCallback(() => { + const animationFinalValue = isActive ? 1 : 0; - Animated.timing(this.animatedValue, { + Animated.timing(animatedValue.current, { toValue: animationFinalValue, duration: 340, easing: Easing.inOut(Easing.ease), useNativeDriver: false, }).start(); - } - - render() { - const rotate = this.animatedValue.interpolate({ - inputRange: [0, 1], - outputRange: ['0deg', '135deg'], - }); + }, [isActive]); - const backgroundColor = this.animatedValue.interpolate({ - inputRange: [0, 1], - outputRange: [themeColors.success, themeColors.buttonDefaultBG], - }); - - const fill = this.animatedValue.interpolate({ - inputRange: [0, 1], - outputRange: [themeColors.textLight, themeColors.textDark], - }); + useEffect(() => { + if (prevIsActive === isActive) { + return; + } - return ( - - - (this.fabPressable = el)} - accessibilityLabel={this.props.accessibilityLabel} - accessibilityRole={this.props.accessibilityRole} - pressDimmingValue={1} - onPress={(e) => { - // Drop focus to avoid blue focus ring. - this.fabPressable.blur(); - this.props.onPress(e); - }} - onLongPress={() => {}} - style={[styles.floatingActionButton, StyleUtils.getAnimatedFABStyle(rotate, backgroundColor)]} - > - - - - - ); - } + animateFloatingActionButton(); + }, [prevIsActive, isActive, animateFloatingActionButton]); + + const rotate = animatedValue.current.interpolate({ + inputRange: [0, 1], + outputRange: ['0deg', '135deg'], + }); + + const backgroundColor = animatedValue.current.interpolate({ + inputRange: [0, 1], + outputRange: [themeColors.success, themeColors.buttonDefaultBG], + }); + + const fill = animatedValue.current.interpolate({ + inputRange: [0, 1], + outputRange: [themeColors.textLight, themeColors.textDark], + }); + + return ( + + + { + // Drop focus to avoid blue focus ring. + fabPressable.current.blur(); + onPress(e); + }} + onLongPress={() => {}} + style={[styles.floatingActionButton, StyleUtils.getAnimatedFABStyle(rotate, backgroundColor)]} + > + + + + + ); } FloatingActionButton.propTypes = propTypes; - +FloatingActionButton.displayName = 'FloatingActionButton'; export default withLocalize(FloatingActionButton); From 2cc40499143d71a8c49eee39434ed03fbeccdf64 Mon Sep 17 00:00:00 2001 From: Marc Glasser Date: Mon, 7 Aug 2023 16:29:41 -1000 Subject: [PATCH 2/4] use Animated.Value --- src/components/FloatingActionButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/FloatingActionButton.js b/src/components/FloatingActionButton.js index a496aef31945..8e10e13c6f7b 100644 --- a/src/components/FloatingActionButton.js +++ b/src/components/FloatingActionButton.js @@ -35,7 +35,7 @@ const defaultProps = { }; function FloatingActionButton({isActive, onPress, buttonRef, translate, accessibilityLabel, accessibilityRole}) { - const animatedValue = useRef(isActive ? 1 : 0); + const animatedValue = useRef(new Animated.Value(isActive ? 1 : 0)); const fabPressable = useRef(null); const previousIsActive = usePrevious(isActive); From 61b36dd527909b0c7ef016484690489e8c204620 Mon Sep 17 00:00:00 2001 From: Marc Glasser Date: Fri, 11 Aug 2023 09:43:35 -1000 Subject: [PATCH 3/4] prettier --- src/components/FloatingActionButton.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/FloatingActionButton.js b/src/components/FloatingActionButton.js index 8e10e13c6f7b..db5f3eda9a55 100644 --- a/src/components/FloatingActionButton.js +++ b/src/components/FloatingActionButton.js @@ -47,11 +47,11 @@ function FloatingActionButton({isActive, onPress, buttonRef, translate, accessib const animationFinalValue = isActive ? 1 : 0; Animated.timing(animatedValue.current, { - toValue: animationFinalValue, - duration: 340, - easing: Easing.inOut(Easing.ease), - useNativeDriver: false, - }).start(); + toValue: animationFinalValue, + duration: 340, + easing: Easing.inOut(Easing.ease), + useNativeDriver: false, + }).start(); }, [isActive, previousIsActive]); const rotate = animatedValue.current.interpolate({ From 533ab464c16491765fa531ff56e174c71095dc0b Mon Sep 17 00:00:00 2001 From: Marc Glasser Date: Mon, 20 Nov 2023 10:32:38 -1000 Subject: [PATCH 4/4] Run prettier --- src/components/FloatingActionButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/FloatingActionButton.js b/src/components/FloatingActionButton.js index b85e704840f6..e29a06ffc3d3 100644 --- a/src/components/FloatingActionButton.js +++ b/src/components/FloatingActionButton.js @@ -38,7 +38,7 @@ const defaultProps = { }; function FloatingActionButton(props) { - const animatedValue = useRef(() => new Animated.Value(props.isActive ? 1 : 0)); + const animatedValue = useRef(new Animated.Value(props.isActive ? 1 : 0)); const previousIsActive = usePrevious(props.isActive); const fabPressable = useRef(null);