Transitions in React - Why Doesn't this Work?

Hi FCC,

I’ve been working on the recipe box project over the last few days and I’m finally done aside from putting on some finishing front-end touches. Right now I am trying to animate my modal box to make it slide down from the top of the page.

My CSS looks like this:

.modal {
  background: white;
  text-align: center;
  position: absolute;
  top: 0;
  left: 50%; /* position the left edge of the element at the middle of the parent */
  transform: translate(-50%, -50%);
  width: 400px;
  height: 175px;
  outline: 1px solid black;
  transition: top 350ms ease-in-out;
}

.move-modal {
  top: 45% /*center it vertically*/
}

In my modal component I have the follow code to add the move-modal class to the modal element after it renders.

componentDidMount(){
  this.refs.modal.className += ' move-modal';
}

Everything seems to be working as I expect it to — When a user clicks the “Add Recipe” button, the componentDidMount() hook does fire. The class is added to the modal correctly and the top: 45% is applied. However, the transition does not seem to work. Even more curious if in my CSS I uncomment/re-comment the top:45% the animation works --> the modal will gradually move animate from top 0 to top 45.

Could anyone lend a hand?

Thanks very much!

HI @Swoodend

I can’t say for sure if this will definitely fix it, but the proper way to add a class in JS for modern browsers is to use classList.add: this.refs.modal.classList.add('move-modal'). It’s possible the way you’re doing it isn’t triggering the change under the hood.

Having said that, a better way to do this in React is to use state, rather than manipulating the underlying DOM element.

constructor() {
  this.state = {
    moveModal: false
  }
}

componentDidMount() {
  this.setState({ moveModal: true })
}

render() {
  return (
    {...}

      // This uses Jed Watsons classnames libray
      // If you didn't want to use it, you could do className={`modal ${this.state.moveModal && 'move-modal'}`}
      <div className={classNames({
        modal: true,
        'move-modal': this.state.moveModal
      })}>
        {modal stuff... }
      </div>

    {...}
  )
}

Thanks @joesmith100 . I tried out your suggestion but got the same result. I did a little bit more digging and found this tool https://facebook.github.io/react/docs/animation.html offered by the Facebook folks and had mixed results with it. Instead of sliding down from the top of the screen to the middle my modal would just wait .3 seconds at the top and then jump to the middle. I might do some more playing around with it and hopefully it will work.

Also appreciate the advice about not manipulating the DOM - that’s a core tennant of react!! Adding a class to one element didnt feel like dom maniuplation to me but it definitley is! Thanks :smiley: