Reusing ReactTransitionGroup animations with Higher-order Components
In my previous post we went over how to make a simple box animate when it enters and leaves a TransitionGroup.
If you recall, to give components inside the TransitionGroup flexibility to have differing animations, the TransitionGroup does not define animations itself, but will call the corresponding enter or leave animation hooks on its child components when they are added or removed.
But there are often times when we do want several components to share the same animation, preferably without duplicating code. That can be achieved using Higher-order Components (HOC). (If not already familiar with HOCs, here’s a good intro)
Extracting the animations
Let’s take another look at the Box component from our previous exercise
We can extract the parts specific to animation into a higher-order component called `fadesUp`
Any component that wishes to have that animation behavior can be passed into `fadesUp` and enhanced.
Here’s what that would look like for our Box
Or, if you have decorators enabled (see Using ES7 Decorators with Babel 6)
Let’s make a circle and give it the same animation
Say we want to have animations take 0.3 seconds by default, but set the duration for Box’s animations take 0.8s.
This is what we want to be able to do:
We’ll have to modify our previous `fadesUp` to receive optional `options`, but due to the way that decorators work, it’s not quite as easy as adding an optional second parameter.
Here’s how we’ll have to modify the `fadesUp` HOC:
`fadesUp` now checks to see whether the type of the first argument received is a `function`, which would be when no options were passed and we assume we received a React class (es6 classes have typeof === “function”), so we immediately enhance it. If it did not receive a function, it assumes it received `options`, and returns a partially applied function that when next invoked will enhance the component passed to invoke it using the previously received `options`.
It might be easier to understand why `fadesUp` had to be written the way it was after seeing how the HOC would be used without ES7 decorators:
Here’s what it looks like put together:
You could take this even further and pass all the animation options as part of the options.
The next parts will be on integrating with react-router and coordinating nested animations.
More on Higher-order Components:
Structuring React Applications: Higher-Order Components
Follow Chang Wang on Twitter