giladgo
giladgo

Reputation: 393

Lifecycle events on ReactCSSTransitionGroup's component?

Is there a way to get notified of transition lifecycle events on a ReactCSSTransitionGroup's parent component? For example, if I have the following:

<ReactCSSTransitionGroup
    transitionName={transitionNames}
    transitionEnterTimeout={250}
    transitionLeaveTimeout={250}
    component={MyParent}>
      ...
</ReactCSSTransitionGroup>

I'd like MyParent to accept either lifecycle events, or an isTransitioning-like prop, so that I can (for example) render a different className based on whether a transition is happening or not.. something along the lines of

const MyParent = (props) => {
    if (props.isTransitioning) { // or something
        return <div className="animating" { ... props } />
    } else {
        return <div { ... props } />
    }
}

Is there a way to make this work? Can I know if a ReactCSSTransitionGroup is currently transitioning? All I can see is that the lifecycle events are fired on the child components entering or leaving the group, and not on the container component itself.

Upvotes: 2

Views: 356

Answers (1)

alunyov
alunyov

Reputation: 943

I'm not sure about passing Parent component to the ReactCSSTransitionGroup. I would recommend another approach: simply wrap <MyComponent /> with <ParentComponent /> and setup callback props in <MyComponent /> like so:

Link to the plunkr example -> https://plnkr.co/edit/hSRpiVIVQkZlYjyh2SuD?p=preview

Short explanation: Each item in the list has CSS-class .item

.item {
  transition: opacity 250ms ease-in;
}

Once animation for the .item completed React (starting from v15) will fire the onTransitionEnd callback and will pass this information to the parent component.

And I've added callback onBeforeItemTransition to tell the <Parent /> component, that something gonna happen soon, the transition should start.

var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;

var ParentComponent = React.createClass({
    render() {
      return <MyComponent
      onItemTransitionEnd={(item) => {
        console.log('Transition end for item', item);
      }} />
    }
});

var MyComponent = React.createClass({
  
  getInitialState() {
    return {
      items: ['Item #0']
    }
  },
  
  getDefaultProps() {
    return {
      // We need to call this before we are starting animate items
      onBeforeItemTransition: function() {
        console.log('Transition started!');
      },
      // This should be called after ctra
      onItemTransitionEnd: function() {
      }
    }
  },
  
  addItem() {
    var newItems =
      this.state.items.concat(['Item #' + (this.state.items.length)]);
    this.setState({items: newItems});
    this.props.onBeforeItemTransition();
  },
  
  render() {
    
    var items = this.state.items.map((item, index) => {
      return <div className="item" key={item} onTransitionEnd={this.props.onItemTransitionEnd.bind(this, item)}>
        {item}
      </div>
    });
    
    return <div>
    <button onClick={this.addItem}>Add item</button>
    <ReactCSSTransitionGroup
     transitionName="example" 
     transitionEnterTimeout={250} 
     transitionLeaveTimeout={250}>
      {items}
    </ReactCSSTransitionGroup>

    </div>
  }
  
});


ReactDOM.render(
  <div>
    <h1>Rendered from script.jsx!</h1>
    <ParentComponent />
  </div>,
  document.getElementById('example')
);

Upvotes: 3

Related Questions