Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transitions not applying when component mounts with React@16 #216

Closed
igorrmotta opened this issue Oct 3, 2017 · 18 comments
Closed

Transitions not applying when component mounts with React@16 #216

igorrmotta opened this issue Oct 3, 2017 · 18 comments

Comments

@igorrmotta
Copy link

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
When trying to apply the transition on componentDidMount, the transition effect does not work.

Steps to reproduce:

  1. create-react-app [project-name]
  2. cd [project-name]
  3. yarn add react-transition-group
  4. Copy content from here and paste on the src/App.js
  5. Copy this code and past into src/App.css
.fade {
  opacity: 0;
  transition: opacity 4s linear;
}
.fade.in {
  opacity: 1;
}

What is the expected behavior?
The transition effect should be applied when the componentDidMount is fired. However, it doesn't happen.
If you comment the line 46 and uncomment the setTimeout(() on line 48, 49, 50, 51. It will fix the bug.

Which versions, and which browser / OS are affected by this issue? Did this work in previous versions?
This bug only reproduces with the latest version of React (16).

something tells me that it is related to the new react fiber architecture

@tobias-zucali
Copy link

I think I have the same problem… This is just the samples for Transition & TransitionGroupfrom the docu page merged together.

What is the expected behavior?
Items are faded in as they are added.
The function inside Transitionin is called with state exited, entering and entered, if I place a debugger there the animation works fine. Without the debugger there is no fade effect.
It seems that React 16 optimised the rendering so well that there is no redraw cycle between exited and entering, which destroys our animation effect.

Which versions, and which browser / OS are affected by this issue?
react: ^16.0.0
react-dom: ^16.0.0
react-transition-group: ^2.2.1

import React from 'react';
import TransitionGroup from 'react-transition-group/TransitionGroup';
import Transition from 'react-transition-group/Transition';

const duration = 300;

const defaultStyle = {
  transition: `opacity ${duration}ms ease-in-out`,
  opacity: 0,
}

const transitionStyles = {
  entering: { opacity: 1 },
  entered:  { opacity: 1 },
};

const Fade = ({ in: inProp, children, ...otherProps }) => (
  <Transition in={inProp} timeout={duration} { ...otherProps }>
    {(state) => (
      <div style={{
        ...defaultStyle,
        ...transitionStyles[state]
      }}>
        { children }
      </div>
    )}
  </Transition>
);

class AnimationGroup extends React.Component {
  constructor(props) {
    super(props)
    this.state = {items: ['hello', 'world', 'click', 'me']}
  }
  handleAdd() {
    const newItems = this.state.items.concat([
      prompt('Enter some text')
    ]);
    this.setState({ items: newItems });
  }
  handleRemove(i) {
    let newItems = this.state.items.slice();
    newItems.splice(i, 1);
    this.setState({items: newItems});
  }
  render() {
    return (
      <div>
        <button onClick={() => this.handleAdd()}>Add Item</button>
        <TransitionGroup>
          {this.state.items.map((item, i) => (
            <Fade key={item}>
              <div>
                {item}{' '}
                <button onClick={() => this.handleRemove(i)}>
                  remove
                </button>
              </div>
            </Fade>
          ))}
        </TransitionGroup>
      </div>
    );
  }
}

export default AnimationGroup;

yannisgu added a commit to yannisgu/react-transition-group that referenced this issue Oct 15, 2017
Extracted the initial transition from EXITED to ENTERING to setTimeout, so that a paint will be done between. Else it is not possible to do CSS transitions, as the browser will not interpret changes to CSS properties as change.
@yannisgu
Copy link

I made a proposal for a workaround this issue: #227

@jquense
Copy link
Collaborator

jquense commented Oct 16, 2017

Check out previous issues on this. Transition is a low level component with no specific affordances for css transitions, those need to be handled in the wrapping component (or use CssTransition).

In this particular case you don't need a timeout you can reflow the browser, there are a few examples of this in previous issues and the components link in the note about it in the docs

@jquense jquense closed this as completed Oct 16, 2017
@TheSharpieOne
Copy link

@jquense users should not expect Transition to work the same with react 16 as it does with react 15? I didn't see that in the note about it in the docs.
If that is not the case then one of the two is broken since they currently work differently.
Also, what previous issues are you referring to? I looked at all of the react 16 related issues in this repo and didn't see anything similar to this.

@lucsky
Copy link

lucsky commented Oct 18, 2017

@TheSharpieOne I think @jquense is probably refering to #159. There are others but this one specifically discusses the manual reflow.

@Kielan
Copy link

Kielan commented Jan 1, 2018

where does this issue end?

@johot
Copy link

johot commented Apr 16, 2018

I wish there was an option to fix this reflow issue out of the box. The CSSTransition doesn't really support using variables which I needed in my general purpose Fade animation component.

I solved this by not using appear in my <Transition/> component and instead used a setTimeout of 1 ms in my componentDidMount and then after 1 ms I would render the <Transition/> component using in={true}. This fixed the issue mentioned here.

@silvenon
Copy link
Collaborator

silvenon commented Apr 16, 2018

CSSTransition is built upon Transition, you should be able to do anything that you can do with Transition, with the addition of classes and reflow hack.

<CSSTransition in={in} timeout={200}>
  {state => (
    // ...
  )}
</CSSTransition>

@thatisuday
Copy link

@silvenon What is reflow hack? :/

@silvenon
Copy link
Collaborator

CSSTransition forces a reflow in order for entering/appearing styles to work.

@krabbypattified
Copy link

+1 👍 CSSTransition is breaking my CSS transition attributes

@silvenon
Copy link
Collaborator

silvenon commented Jun 5, 2018

@krabbypattified could you open a new issue providing a demo?

@krabbypattified
Copy link

krabbypattified commented Jun 6, 2018

Here is a demo. Hover over anything and hover/click on the pink circle. There is no transition in circle size. When I set the in attribute to always true, the circles now transition in size when I hover/click on them and everything works as expected.

https://codesandbox.io/s/ojzkr98m4y

@krabbypattified
Copy link

I will open a new issue.

@silvenon
Copy link
Collaborator

silvenon commented Jun 6, 2018

@krabbypattified feel free to include the same demo, you don't have to use our template.

@tr3v3r
Copy link

tr3v3r commented Oct 22, 2018

Use keyframes instead. Works good for me.


  &.fadeIn {
     animation-name: fadeIn;
     animation-duration: 1s;
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}```

@GeekStocks
Copy link

Hell yeah! @tr3v3r thank you!

Holy shit this issue has like 4 "solutions" none of which work. Its a simple opacity change —been doing it for years— but wow do React components wreak havoc. Only thing I did different was add the fill-mode so that the faded-in effect would stick around:

.fadeIn {
  animation-name: fadeIn;
  animation-duration: 2s;
  animation-fill-mode: forwards;
}

Its just like what Scotty said:

The more they overthink the plumbing, the easier it is to stop up the drain.

@silvenon
Copy link
Collaborator

silvenon commented Mar 5, 2019

I recommend using CSS Transitions instead, that's the feature that react-transition-group was built for. Like we previously said, most of the times what you really need is the CSSTransition component, not Transition. The author of the issue was trying to reinvent the appear prop and reflow hack at the same time, even though those features already exist (the docs were probably worse then, so I understand the confusion). I guess React 16 is making some kind of an optimization that breaks those hacks, but that doesn't diminish the fact that it's not the way this library should be used. I don't know what's the reason behind trying to reinvent these features, it's not clear from the examples, but I'd be happy to clear it up if anyone still has questions. I feel uneasy with the keyframes being considered as a fix because I don't think there was a problem to begin with. 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests