azangru
azangru

Reputation: 2748

React Motion: Leaving object becomes visually indistinguishable from entering object

I am trying to create a basic animation with React Motion: I have two elements, either of which can be displayed depending on the component state. When the state changes, I want one element to replace the other. The replacement animation is a combination of sliding to the left and fading out of the leaving element.

Problem: When the state is changed, the leaving element becomes indistinguishable from the entering element.

Illustration: Here, in the codepen where I reproduced the problem, clicking on a colored shape will change the component's state and will replace the element. Notice that the leaving component becomes the same as the component that enters (e.g. when a circle is clicked, it changes to the square and leaves). I would expect the leaving element to remain its initial shape.

Here is the copy of the code of the component from CodePen:

const spring = ReactMotion.spring;
const TransitionMotion = ReactMotion.TransitionMotion;

class App extends React.Component {

 constructor(props) {
    super(props);
    this.state = {
      mode: 'foo'
    }
  }


  changeMode() {
    const { mode: currentMode } = this.state;
    this.setState({
      mode: currentMode === 'foo' ? 'bar' : 'foo'
    });
  }

  willEnter() {
    return { opacity: 0, translateX: 200 };
  }

  willLeave() {
    return { opacity: spring(0), translateX: spring(-200, { stiffness: 140, damping: 20 }) };
  }

  render() {
    const { mode } = this.state;
    const styles = [mode].map(mode => {
      return {
        key: mode,
        style: {
          opacity: spring(1),
          translateX: spring(0, { stiffness: 140, damping: 12 })
        }        
      }
    });

    return (
      <div className="container">
        <TransitionMotion
          styles={styles}
          willEnter={this.willEnter}
          willLeave={this.willLeave}
         >
          { interpolatedStyles =>
              <div style={{ position: 'relative' }}>
              {
                interpolatedStyles.map(config => {
                  return mode === 'foo' ? this.renderFoo(config) : this.renderBar(config);
                })
               }
              </div>
          }
        </TransitionMotion>
        <div className="label"> Click the shape </div>
      </div>
    );

  }

  renderFoo(config) {
    console.log('config', config);
    return (
      <div
        key={config.key}
        style={{
          position: 'absolute',
          top: 0,
          left: 0,
          width: '150px',
          height: '150px',
          borderRadius: '100%',
          backgroundColor: 'red',
          opacity: config.style.opacity,
          transform: `translateX(${config.style.translateX}%)`
        }}
        onClick={ () => this.changeMode() }
      />
    );
  }

  renderBar(config) {
    return (
      <div
        key={config.key}
        style={{
          ...config.styles,
          position: 'absolute',
          top: 0,
          left: 0,
          width: '150px',
          height: '150px',
          backgroundColor: 'blue',
          opacity: config.style.opacity,
          transform: `translateX(${config.style.translateX}%)`
        }}
        onClick={ () => this.changeMode() }
      />
    );
  } 

}

Could you please suggest how to fix the animation so that the leaving element was visually the correct one?

Upvotes: 0

Views: 181

Answers (0)

Related Questions