How to make this fade in on each onPress event (or state change)?

240 Views Asked by At

The component below fades in the first time it's displayed. When the onPress is fired from the RadioInputWidget, the control that consumes CompetencyView changes its state and then CompetencyView is updated with new parameters values. This all works fine.

What I want is for the control to fade in again each time onPress is fired. Whether it's directly tied to the fact that onPress fired, or whether it's a direct result of the fact the state has changed doesn't really matter to me though I assume one method would be a better practice than the other. Unfortunately, I can't figure out how to make it work either way.

const CompetencyView = ({ pageNumber, competencyName, question, skillText, scaleDescriptions, responseValue, onPress }) => {
  const fadeAnim = useRef(new Animated.Value(0)).current  // Initial value for opacity: 0

  React.useEffect(() => {
    Animated.timing(fadeAnim, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: true
    }).start();
  }, [fadeAnim])
  
  return (
    <LinearGradient style={{flex: 1}} colors={['#ff0000', '#ff492b', '#770000']}>
      <Animated.View style={{flex: 1, backgroundColor: 'red', opacity: fadeAnim  }}>
        <View style={competencyStyles.View}>
          <Text style={competencyStyles.Heading}>{competencyName}</Text>
          <Text style={competencyStyles.Question}>{question}</Text>
          <Text style={competencyStyles.SkillText}>{skillText}</Text>
          <RadioInputWidget onPress={onPress} selectedIndex={responseValue} scaleDescriptions={scaleDescriptions} />
          <RadioPagerWidget selectedIndex={pageNumber} />
        </View>
      </Animated.View>
    </LinearGradient>
  );
};
2

There are 2 best solutions below

0
On

Try this, but I'm not sure it works. Tell me if it works for you.

const [opacity, SetOpacity] = useState(new Animated.Value(0))

...
React.useEffect(() => {
    Animated.timing(fadeAnim, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: true
    }).start();
  }, [opacity])

...
<RadioInputWidget onPress={() => SetOpacity(opacity.setValue(0))} .../>
0
On

You can create a function to perform fading animation. Even if the view has been animated once, it will restart it from initial value.

const animate = () => {
    fadeAnim.setValue(0);
    Animated.timing(fadeAnim, {
      toValue: 1,
      duration: 1000,
      useNativeDriver: true
    }).start();
  }

The you modify your useEffect like this:

  React.useEffect(() => {
    animate()
  }, [fadeAnim])

Create a function to handle press action on RadioInput.

  const onPressRadioInputWidget = () => {
     animate();
     onPress();
  }

Instead of calling onPress directly, we'll call onPressRadioInputWidget. This will cause the view to fade in each time the widget is pressed.

<RadioInputWidget 
    onPress={onPressRadioInputWidget} 
    selectedIndex={responseValue} 
    scaleDescriptions={scaleDescriptions} 
/>