Vue.js render functions and transitions

If you are using JSX / render functions with Vue.js and were wondering how to do transitions, here’s what you need to know

Photo by Roland Larsson on Unsplash

The documentation for Vue.js transitions leaves a lot to be desired when it comes to documented-but-less-common render functions. This includes users that, like me, use JSX with Vue.js. This short article will show you how to do transitions in this particular scenario.

I use JSX in the examples, but it all works with plain JavaScript render functions as well, since JSX is just a syntactic sugar for calls to h(). If you want to know more about this topic, look at this article.

How transitions work anyway

The gist of transitions is that you have a transition component (built-in), which assigns classes to elements that get mounted (enter) or unmounted (leave).

The peek-a-boo dance

The tricky part is where elements must get mounted or unmounted. This can be accomplished in several ways.

If you want your element to toggle (appear and disappear), you can use the usual ternary:

render(h) {
<transition>
{this.showDiv ? <div class="myDiv">Hello</div> : null}
</transition>
}

If you want your element to be swapped with another element, again, you can use the ternary:

render(h) {
<transition>
{this.showOneOrTheOther
? <div class="myDiv">Hello</div>
: <div class="myOtherDiv">Hello again</div>
}
</transition>
}

Nope, I was just kidding. No, you can’t use the ternary alone to swap out elements like that. What happens is that the diffing algorithm decides that there’s already an element there, so instead of removing it from the DOM, it just patches it to look like the other element.

You need to use the key prop if you are swapping two elements.

render(h) {
<transition>
{this.showOneOrTheOther
? <div key="myDiv" class="myDiv">Hello</div>
: <div key="myOtherDiv" class="myOtherDiv">Hello again</div>
}
</transition>
}

With the key prop in place the two elements get swapped completely (old one gets unmounted, and new one mounted in its place) as long as the keys differ.

Similarly, if you want to swap a component or an element with a different version of itself:

render(h) {
<transition>
<div key={this.subcomponentKey}>
<MyComponent />
</div>
</transition>
}

In the above example the this.subcomponentKey method is going to somehow calculate an appropriate key for the MyComponent component.

The key is in the difference

While we are on the topic of keys, remember that elements/components always gets rendered completely (no diffing done) when the key changes. On the other hand, as long as the key remains the same, the elements/components are left completely intact.

Don’t let that catch you off-guard. Before haphazardly adding a key to just about anything that moves (or should move), think carefully what the value of that key should be. Test without the key first, note the results, and then add a key, and see if you can replicate the same effect. If the UI won’t update, you probably picked the wrong key value.

Adding animation

Now that we know how to make our elements go away and come back, it’s time to work on the animation.

In the simplest case, we have two classes. One class is always applied, and another one is applied when the element / component is about to get mounted or unmounted.

// my.css.base {
transition: transform 1s;
}
.out {
transform: translateX(-100vw);
}

And apply those classes:

render(h) {
<transition enter-class="out" leave-to-class="out">
{this.someProp ? <div class="base">Hello</div> : null}
</transition>
}

The enter-class and leave-to-class are documented in the Vue.js documentation, so read up on them there. I’ll explain only those two here.

The enter-class is a HTML class name for the styles that get applied right after the element is mounted. Immediately after that, the class is removed. We add transitions to create animations between the time when enter-class class is applied, and the time when it’s not (when only the .base class is applied).

The leave-to-class is applied just before the element is about to be removed. Vue.js then waits for whatever animation you have to end, and then removes the element from the DOM tree. Again, we use transitions to create an animation.

In our example, we used the exact same .out class for both enter and leave, but we can use different classes for the two events.

Conclusion

Hopefully you now understand the key concepts (pun intended) of Vue.js transitions when used in render functions and with JSX. Vue.js transitions offer a lot more features though, like the ability to hook into transition events using JavaScript, and therefore do even some stuff unrelated to animation (kinda like lifecycle hooks). I’ll end the article here, though, and leave the experimentation to my dear readers. Happy hacking!

Hajime Yamasaki Vukelic

Written by

On a never-ending quest for code clarity, better software designs, and pleasure of work.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade