tom harrison
tom harrison

Reputation: 3433

React animate with CSSTransitionGroup on toggle

I am trying to get a transition between components entering and leaving when the button is clicked to toggle between state

I have also tried putting <UserDetails /> and <UserEdit /> as seperate components but have the same result in that no animation is triggered.

https://www.webpackbin.com/bins/-KjIPcMeQF3iriHRqTBW

Hello.js

import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup'
import './styles.css'
export default class Hello extends React.Component {
constructor() {
super()

this.state = { showEdit: false }
this.handleEdit = this.handleEdit.bind(this)
}

handleEdit() { this.setState({ showEdit: !this.state.showEdit }) } 

render() {

 const UserDetails = () => (
 <div className="componenta" key="1">UserDetails</div>
 )
 const UserEdit = () => (
 <div className="componentb" key="2">UserEdit</div>
 )

return(
<div >
    <CSSTransitionGroup 
      transitionName="example"
      transitionEnterTimeout={10}
      transitionLeaveTimeout={600}>
    {this.state.showEdit ? <UserDetails /> : <UserEdit />}
    </CSSTransitionGroup>
    <button onClick={this.handleEdit}>Toggle</button>
</div>
)
}
}

styles.css

.thing-enter {
 opacity: 0.01;
 transition: opacity 1s ease-in;
}

.thing-enter.thing-enter-active {
  opacity: 1;
}

 .thing-leave {
  opacity: 1;
  transition: opacity 1s ease-in;
 }

 .thing-leave.thing-leave-active {
  opacity: 0.01;
 }

Upvotes: 2

Views: 3761

Answers (2)

tom harrison
tom harrison

Reputation: 3433

Here is a working example using display:none to hide the unmounting component

enter link description here

Upvotes: 0

Gregor Menih
Gregor Menih

Reputation: 5126

You have your key attribute set to the wrong item - the <div> is not the direct descendant of CSSTransitionGroup (because your wrapped it into a component by defining it as a function), so it doesn't know which items were added or removed. You have to set your keys to UserDetails and UserEdit, so CSSTransitionGroup can properly determine changes in it's children.

Here is your render method that works:

render() {

    const UserDetails = () => (
      <div className="componenta">UserDetails</div>
    )
    const UserEdit = () => (
      <div className="componentb">UserEdit</div>
    )
    return(
    <div >
        <CSSTransitionGroup 
          transitionName="example"
          transitionEnterTimeout={10}
          transitionLeaveTimeout={600}>
        {this.state.showEdit ? <UserDetails key="1" /> : <UserEdit key="2" />}
        </CSSTransitionGroup>
        <button onClick={this.handleEdit}>Toggle</button>
    </div>
    )
  }

An alternative would be to store UserDetails and UserEdit into variables and then render them as such. That will allow you to leave the key attributes where they are now, instead of moving them.

Upvotes: 1

Related Questions