In React Transition Group, there are two components at our disposal for transitions of singular components; <Transition>
and <CSSTransition>
. In this lesson, we’re going to discuss the key feature that CSSTransition has over Transition, i.e. forcing reflows to make more complex transitions more predictable. We’ll also look at how to use the key props of any transition; in
, timeout
, and children
.
Instructor: [00:00] In this example, we have a menu button which, when clicked on, toggles a menu which appears underneath. The way this works is as simply as possible, using React state. The onClick fires this toggle method, which updates some state. The stateful value then controls the appearance of the menu.
[00:24] Let's say we want to transition this balloon menu over time, so that it doesn't appear and leave straight away. Instead, it smoothly transitions in and out. To do this, we're going to make use of React Transition Group.
[00:41] As a dependency, let's install React Transition Group. Then we're going to import CSSTransition from React Transition Group. The CSSTransition component is going to allow us to apply CSS transitions to elements entering and leaving the DOM.
[01:03] Let's head back down to the render method. We're going to replace this line that refers to this.state.showBalloon. We'll replace it with a CSS transition. It's still going to be controlled by that stateful value, but we're going to pass it to the in prop.
[01:25] The in is a Boolean value, which is going to control the appearance of the menu. We'll also supply a timeout value, which is going to be the amount of milliseconds it will take to enter or leave. We'll pass it a classnames prop, which is going to be a string. It's going to be called balloon.
[01:47] We're going to need this when we apply our CSS for the transition. Lastly, we're going to pass the unmountOnExit prop. This will mean that when this menu disappears, it's actually going to leave the DOM completely. This is an extremely useful feature of CSS transition.
[02:10] Let's see how this affects what we have so far. Now, when the menu leaves, there's 350 millisecond delay, which will allow us to apply a transition. Our render method looks good. Let's head over to our CSS.
[02:25] In our CSS, we have a list of variables at the top which control the colors and the measurements of the button and the menu. We also have a timeout value down here, which is the same as the timeout value that we used in the render method.
[02:44] Below these variables are styles for the button, the menu, and the list inside the menu. Underneath this, we're going to write some styles for a transition. We passed the class name of balloon, so we're going to write transitions pertaining to the balloon class name.
[03:06] CSSTransition gives us four key class names to use for elements entering and leaving. We have balloon-enter, balloon-enter-active, balloon-exit, and balloon-exit-active. balloon-enter will fire immediately when the element enters the DOM.
[03:34] balloon-enter-active will apply on the next tick after balloon-enter. This is where we can add a transition. balloon-exit will fire immediately when the stateful value turns false, and balloon-exit-active will fire on the next tick after that. Then the element will leave the DOM.
[03:57] Let's say we want to just do a simple fade as the transition. It's going to fade into the DOM and fade back out. We'll use opacity for that. In balloon-enter, we're going to say opacity zero. balloon-enter-active will have opacity one.
[04:14] It's going to have a transition on it. We're going to transition opacity, and we can use the timeout that we declared at the top of this file. balloon-exit will start with opacity one. It will transition to opacity zero. We need to add the transition in order to do this.
[04:45] Let's save and refresh. Now, when we open our menu, we get a fade in effect. Let's slow this down, so that we can see exactly what's going on. I'm going to change the timeout to 3.5 seconds, up from 350 milliseconds.
[05:08] Let's inspect inside the DOM. When this button is pressed, we're going to see the menu appear into the DOM with balloon-enter and balloon-enter-active on it. When it's completed, we get balloon-enter-done, which is also a targetable class name.
[05:29] When the stateful value turns false, we get balloon-exit, balloon-exit-active, and then it leaves the DOM entirely. Of course, if we want to, we can be is elaborate as we want with our transition. Let's switch the timeouts back.
[05:52] Let's say we want our balloon to grow out from this menu. We'll apply a top value, a width, a max height, a color, and a background color. All these values are going to transition to their finishing values. Menu starting top becomes menu ending top, etc.
[06:24] For the transition, we're going to transition everything. For the exit class names, we apply the same principle as before. balloon-enter and balloon-exit-active actually have the same values, because they're the starting and ending states of our transition.
[06:49] Similarly, balloon-enter-active and balloon-exit have the same values, but the transitions are on the active class names. Let's save and refresh. Now, we have a menu which grows out from the button.
Good explanation, however transitioning on width and height is not a good idea and may cause performance issues on a medium/large sized DOM.
Hi Steve, the code is available in the Codesandbox link above 👍
Hi cdn34, thanks for the input! As you can see I have very few DOM elements in these examples. Feel free to adjust your transition properties as per your use case 👍
Correct me if I'm wrong, your Codesandbox seems to already contain the completed transition? In your video: "00:24 Let's say we want to transition this balloon menu over time, so that it doesn't appear and leave straight away." How do I code along with this? Am I not being clear? Many of us learn better by doing rather than just watching a short video. So we need the code in the state you start the lesson.
Hi Steve, no problem! Here's the code before any transitions are added: https://codesandbox.io/s/kxvy25zy5v
Hope this helps!
if we animate transform: translateX()
the animation doesnt work, and goes back to initial class style as soon as *-active class is removed. Can someone please tell me why.
Codesandbox - https://codesandbox.io/s/p9jpw90jwj
Could we please have a link to the code in it's start state so that we can code along? I know I'm not the only one who learns better this way.