How to animate a React component on render?
Asked Answered
D

3

5

I am trying to animate a React component that contains data fetched from elsewhere. Placing it in a ReactCSSTransitionGroup worked fine. That is, until I altered the component's render() method to return false until the data has been fetched (to prevent it from being rendered without data).

Now, I guess the component is mounted immediately, at which point the animation classes are added, but only rendered afterwards. Is this thinking correct? How can I get the component to be animated when render returns the actual component?

Driveway answered 1/3, 2015 at 17:26 Comment(2)
Can you show us the code you have written so far? (That is not working properly)Hendrik
I was working on a fiddle but it took too much effort when it seemed I had a lead. Turned out that lead didn't help, so I'll see if I can cook something up soon.Driveway
A
6

ReactCSSTransitionGroup activates whenever components are added and deleted to its props.children. Since your component is mounted before you fetch data, nothing will happen after data is fetched (I think this is true even if the component's render() method returns false. Let me know in the comments if that is incorrect)

Here's a solution

Just don't mount the component (in the solution, it's a <div key="1"> tag) until the react class receives the data. Use component states on the parent component to keep track of the state of your asynchronous request.

Anglocatholic answered 3/3, 2015 at 11:37 Comment(5)
Thanks for the fiddle. I see how this does the animation correctly, but the fetching of the data is relevant to the child component, not the parent. In fact, different children do so in different ways. It also feels like the children should by themselves decide whether they should be rendered or not - otherwise, the element's behaviour is dependent on the component it is located in. Thus, I'd rather have the component be animated on render rather than on mount, then alter when the component is mounted.Driveway
Unfortunately, I can't really think of a way to do that because the ReactCSSTransitionGroup's lifecycle is triggered when a component is added to its children. If the component is already there, you won't be able to re-trigger the animation without unmonuting and remounting the component. It doesn't feel that unnatural to me for the parent to determine whether or not its children should be rendered, because the parent is actually decides whether or not to return the children in its render() method. Is there a reason you want the result of the child's render() to cause the animation?Anglocatholic
Hmm, bummer.. The child is responsible for getting it's data fetched, and would have to expose the result to its parent to have that decide. I was holding off on trying to implement Flux until I got to grips with React, but perhaps it's time for me to start implementing - then maybe your answer makes more sense. I'll let it know if it does :)Driveway
I recommend fetching the data with the parent, and once data is received, create the child. Another alternative is to have each child return an empty <ReactCSSTransitionGroup> tag, and when the child fetches its data, you start returning ReactCSSTransitionGroup with the child nested inside of it.Anglocatholic
I've now implemented data fetching in a Reflux action, to be saved in a Reflux store and which is triggered from the parent - as you suggested. When the data is available, the children are then added and are, indeed, animated nicely. Thanks for your help!Driveway
R
1

The ReactCSSTransitionGroup doesn't play nicely with tables as it's default behaviour is to wrap tags with a span element. You can provide it with your own component, but I found the solution quite heavy and complex.

I have a different approach that allows a React component to animate each time its content changes. The animation is continually triggered by toggling between 2 duplicate CSS styles.

Roughspoken answered 1/2, 2016 at 10:21 Comment(0)
H
0

Other than the ReactCSSTransitionGroup, another way is to write your own css transitions with an 'enter' class that is added to the component in componentdidmount. Keep in mind that you should change the state in a requestAnimationFrame because otherwise your class would be added in the same event loop as it is mounted, thus wont animate. Here's an example: https://codesandbox.io/s/zkm5015y1x

Also, more on event loop, a talk by Jake Archibald: https://www.youtube.com/watch?v=cCOL7MC4Pl0

Hundredpercenter answered 18/12, 2018 at 6:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.