slideToggle() methods. You can say about jQuery what you want, but these methods were very easy and helpful. When I first started using a component based framework such as React I really missed an easy way to mount and unmount content with a fancy transition. For quite some time I have been dependent on the
Transition component from React Transition Group. It gets the job done, but in an era of Hooks and spring physics it’s renderProp API feels a bit outdated and the animations a bit sluggish.
Because we at CLEVER°FRANKE have been a heavy users of Hooks since React
16.8 came out and since React Spring now added a very easy Hooks interface in
v7, I decided to combine the best of both worlds to create a reusable SlideToggle component. Below I will describe my process and choices so it may hopefully help you or others.
The first thing we need to do is make sure we are running a React version that supports hooks and install react-spring via:
npm install --save react-spring
and create a component that will serve as the wrapper element.
The component will have three props:
isVisiblewhich will make sure the children will be mounted and slided down.
forceSlideInwill be an optional prop that makes sure the component slides down on it’s initial render.
childrenwill contain the children elements.
Next we will need to add the actual HTML elements and add references to them so that React can interact with them. The new Hooks API provides the
useRef hook that “returns a mutable ref object whose
.current property is initialized to the passed argument (
initialValue). The returned object will persist for the full lifetime of the component” (See the React docs).
We need a little bit of styling to prevent margins of the children elements from overflowing the container. I’m using Styled Components but you can of course choose any other styling method.
Now it is time for the React Spring magic to come into play. We will be using the
useTransition hook since we are mounting and unmounting the children elements and this hook provides
leave properties just like the Transition component from React Transition Group. These properties allow you to add basic styling objects or more advanced
async functions that can chain multiple style changes. The latter is very useful in our case because we want to calculate the proper final element height and make sure that after that the css
height property is set to
auto. Furthermore we want to control the
overflow property and set it to
visible whenever the animation changes.
useTransition(items, key, config) hook can mount multiple instances of
children at once, for example when the component is toggled before the animation is ended. This is something we want to prevent because we don’t want duplicates of our content showing up. React Spring provides the
unique: true property which will make sure items with the same key will be reused and never rendered more than once. In our case we can omit the
key parameter and set it to
null because we will only animate one single element. React Spring will make sure the elements receives a proper key.
useTransition will return an Array of transitionable element objects each containing an
key that contain respectively a reference to the actual element, the styling properties and the unique key. The styling properties can be applied on an
animated component provided by React Spring which will make sure the styling props are transformed into actual animations.
Almost there! We now have a working SlideToggle component. It is however missing one important feature. At this point the component will always start from
height: 0; also when
true on the components initial render. So we need to make sure that the
from property changes based on the initial value of
isVisible. In order to remember that initial value we can use the
useRef hook again because as said above that will persist the value throughout the lifetime of the component.
const isVisibleOnMount = useRef(isVisible && !forceSlideIn);
And change the
from property to:
from: isVisibleOnMount.current ? visibleStyle : hiddenStyle
You can find a working demo of this component here. Feel free to reuse it!
With a little bit of code we’ve been able to create a reusable and easily customisable SlideToggle component. Adding React Spring to your bundle for only this use case may be a bit overkill but I can assure you that once it’s added to your bundle and you start playing with it, you will certainly find more UI elements that can be brought to life with spring animations!