Dynamic React animations
Did you know that you can dynamically change the transitionName of a React animation on the fly? This is more of a “hey look it works” thing then an actual revelation.
First, a quick primer/review taken from the React animation docs. The CSSTransitionGroup
automatically adds classes to its children when they are added and removed.
<CSSTransitionGroup transitionName="example">{items}</CSSTransitionGroup>
In this case, a new item will be rendered with the .example-enter
class. Immediately after render, the .example-enter-active
class will be added.
By adding some matching CSS, you can cause the entry to be animated using CSS transitions.
.example-enter {
opacity: 0.01;
transition: opacity 0.5s ease-in;
}
.example-enter.example-enter-active {
opacity: 1;
}
CSSTransitionGroup
also adds similar classes when elements leave.
Making the transition name dynamic
One cool aspect of CSSTransitionGroup
is that you can adjust the name on the fly. Among many possibilities, this makes it very easy to dynamically control the direction of a sliding transition.
<CSSTransitionGroup transitionName={`slide-${direction}`}>
{items}
</CSSTransitionGroup>
In my case, I was dealing with a navigation component in which you could drill to various depths. Setting the name is simple, but calculating the desired direction requires a bit of state.
React.createClass({
// ...
componentWillReceiveProps(newProps) {
// `path` is an array of tree node indexes
const direction =
newProps.path.length > this.props.path.length ? "right" : "left";
this.setState({ direction });
},
render() {
// ...
return (
<CSSTransitionGroup transitionName={`slide-${this.state.direction}`}>
{/* ... nav pane ... */}
</CSSTransitionGroup>
);
},
});
This isn’t bad, but I wanted to extract the state and moving parts into a self contained component. With this final product, the only prop you need to pass in is a numeric representation of your depth. The panes will slide transition from right to left as if moving forward when the number increases and vice versa when it decreases.
<SlideTransition depth={path.length}>{/* ... nav pane ... */}</SlideTransition>
The source of the final component is available in a Gist as well as in the CodePen demo embedded below.
See the Pen Directional React Animations by tgecho (@tgecho) on CodePen.