title: Using React TransitionGroup, GSAP, and MobX to Re-Render the Same Component
body: <p>I have a survey-like React application that is rendering various questions to the screen using a variety of UI components. </p>
  
  <p>However, the nature of the survey is that many questions re-render using the exact same component. For instance, an "A / B Selector" or a "Checklist." </p>
  
  <p>What I'd like to achieve is for each component, regardless of whether it is being re-used or mounted to the DOM for the first time, to fade up from the bottom - and fade downward once the user selects the answer. </p>
  
  <p>Here is a very basic example using five questions and a little box:</p>
  
  <pre><code>import React, {Component, PropTypes} from 'react';
  import ReactDOM from 'react-dom';
  
  import { observer, Provider, inject } from 'mobx-react';
  import { observable, computed, action } from 'mobx';
  
  import 'gsap';
  import TransitionGroup from 'react-addons-transition-group';
  
  // STORE
  class APP_STORE {
  
    @observable showingBox = true;
    @observable transDuration = .25;
  
    @observable questionIndex = 0;
  
    @observable questions = [
      {text: 'one'},
      {text: 'two'},
      {text: 'three'},
      {text: 'four'},
      {text: 'five'},
    ];
  
    @computed get currentQuestion() {
      return this.questions[this.questionIndex];
    }
  
    @action testTrans () {
      this.showingBox = !this.showingBox;
      setTimeout(() =&gt; {
        this.questionIndex++;
        this.showingBox = !this.showingBox;
      }, this.transDuration * 1000);
    }
  
  }
  
  let appStore = new APP_STORE();
  
  
  // TRANSITION w/HIGHER ORDER COMPONENT
  function fadesUpAndDown (Component) {
    return (
      class FadesUp extends React.Component {
        componentWillAppear (callback) {
          const el = ReactDOM.findDOMNode(this);
          TweenMax.fromTo(el, appStore.transDuration, {y: 100, opacity: 0}, {y: Math.random() * -100, opacity: 1, onComplete: callback});
        }
  
        componentWillEnter (callback) {
          const el = ReactDOM.findDOMNode(this);
          TweenMax.fromTo(el, appStore.transDuration, {y: 100, opacity: 0}, {y: Math.random() * -100, opacity: 1, onComplete: callback});
        }
  
        componentWillLeave (callback) {
          const el = ReactDOM.findDOMNode(this);
          TweenMax.to(el, appStore.transDuration, {y: 100, opacity: 0, onComplete: callback});
        }
  
        render () {
          return &lt;Component ref="child" {...this.props} /&gt;;
        }
      }
    )
  }
  
  // REACT
  
  @fadesUpAndDown
  class Box extends React.Component {
    render () {
      return &lt;div className="box" ref={c =&gt; this.container = c}&gt; {this.props.data.text} &lt;/div&gt;;
    }
  }
  
  
  @inject('store') @observer
  class Page extends Component {
  
    render () {
      const store = this.props.store;
  
      return (
        &lt;div className="page"&gt;
          &lt;TransitionGroup&gt;
            { store.showingBox ? &lt;Box data={store.currentQuestion}/&gt; : null }
          &lt;/TransitionGroup&gt;
  
          &lt;button className="toggle-btn" onClick={() =&gt; { store.testTrans(); } } &gt;
            test trans
          &lt;/button&gt;
        &lt;/div&gt;
      );
    }
  
  }
  </code></pre>
  
  <p><strong>This works! But...</strong> to pull it off, I have to manually remove the box component from the DOM <em>(in this case via the <code>showingBox</code> observable)</em>, set a timeout for the transition duration, and re-mount the component completely. </p>
  
  <p>Ultimately I guess this is fine but am wondering whether anyone in the SO community has come across a similar scenario with a better way of addressing it since unmount / remount isn't terribly strong React. </p>