1

I have a looping animation that I want the user to be able to change the timings of. Using a redux I have set it up so that the component being animated receives the new timings as props when the user changes them in settings. However this does not change the timings of the sequence (I am guessing it is because the sequence assigns the values of the variable rather than referring to the value of the variable which changes)

class BreatheCircle extends React.Component {
      state = {
            circleAnimation: new Animated.Value(0.6),
            holdAnimation: new Animated.Value(0),
            inhaleAnimation: new Animated.Value(0),
            exhaleAnimation: new Animated.Value(0),
        }
        componentWillReceiveProps(nextProps){
          console.log('next props:', nextProps)
        }

breathAnimation = 
    Animated.loop(
      Animated.sequence([
      Animated.timing(this.state.inhaleAnimation, {toValue: 1, duration:10}),
      Animated.timing(this.state.circleAnimation, {toValue: 1, duration:this.props.in*1000}),
      Animated.timing(this.state.inhaleAnimation, {toValue: 0, duration:10}),
      Animated.timing(this.state.holdAnimation, {toValue: 1, duration:10}),
      Animated.timing(this.state.holdAnimation, {toValue: 0, duration:10, delay: this.props.hold*1000}), //delay for the hold to disappear
      Animated.timing(this.state.exhaleAnimation, {toValue: 1, duration:10}),
      Animated.timing(this.state.circleAnimation, {toValue: 0.6, duration:this.props.out*1000}),
      Animated.timing(this.state.exhaleAnimation, {toValue: 0, duration:10}),
]))


componentDidMount(){
  // this.state.animated.setValue(0.6) // state already declare
  this.animateCircle();
}
componentWillUnmount(){
  this.breathAnimation.stop();
}

animateCircle(){
    this.breathAnimation.start();
}


  render(){
    const{animated} = this.state;
    return(
        <View style={{alignItems: 'center'}}>
        <Animated.View style={{
          width: 350,
          height: 350,
          borderRadius: 200,
          transform: [ {scale: this.state.circleAnimation} ]
        }}>
          <LinearGradient colors={['rgb(255, 206, 224)', 'rgb(248, 120, 131)']} style={{ alignItems: 'center', justifyContent: 'center', flex: 1, borderRadius: 200}}>
            <Animated.Text style={{
              position: 'absolute',
              justifyContent: 'center',
              fontSize: 80,
              fontWeight: 'bold',
              color: 'white',
              opacity: this.state.holdAnimation.interpolate({
                inputRange: [0, 1],
                outputRange: [0, 1],
                extrapolate: 'clamp',
                                },)
                              }}>Hold</Animated.Text>
            <Animated.Text style={{
              position: 'absolute',
              justifyContent: 'center',
              fontSize: 80,
              fontWeight: 'bold',
              color: 'white',
              opacity: this.state.inhaleAnimation.interpolate({
                inputRange: [0, 1],
                outputRange: [0, 1],
                extrapolate: 'clamp',
                                },)
                              }}>Inhale</Animated.Text>
            <Animated.Text style={{
              position: 'absolute',
              justifyContent: 'center',
              fontSize: 80,
              fontWeight: 'bold',
              color: 'white',
              opacity: this.state.exhaleAnimation.interpolate({
                inputRange: [0, 1],
                outputRange: [0, 1],
                extrapolate: 'clamp',
                                },)
                              }}>Exhale</Animated.Text>
          </LinearGradient>
        </Animated.View>
      </View>
    )
  }
}

const mapStateToProps = state => {
  return {
    in: state.in,
    hold: state.hold,
    out: state.out,
  };
};

  export default connect(
    mapStateToProps
  )(BreatheCircle);

How would I make the timings change when the new props are passed to it?

1 Answers1

0

I suggest you to use the lifecycle method componentDidUpdate: if your mapStateToProps works properly, you can simply update the state of your component like this:

componentDidUpdate(previousProps, previousState) {
  if (this.props !== previousProps){
    this.setState({
      ... // update your component state with the props you passed here
    })
  }
}

Here is the doc

Milore
  • 1,672
  • 1
  • 15
  • 20
  • Just to clarify how to set the state: `this.setState({ holdAnimation: this.props.hold });` or whatever you want – Milore Oct 22 '18 at 17:32
  • I have tried this but the update of state doesn't update the animation. I am trying to change the duration of the animations, not the Animated value so I need to restart the animation somehow with the new timings, but the ways I've tried so far haven't worked. – Billy Bromell Oct 23 '18 at 08:27