Read article4 min
Written by Koen Poelhekke
Create a react SlideToggle component with hooks and react-spring
Code
i

Everybody who has been writing Javascript for more than a few years must have come across jQuery’s slideDown() and 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 Process

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.

SlideToggleContent component

The component will have three props:

  • isVisible which will make sure the children will be mounted and slided down.
  • forceSlideIn will be an optional prop that makes sure the component slides down on it’s initial render.
  • children will 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.

Add HTML elements with proper references

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 from, enter and 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.

The 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 item, props and 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.

Animate height via useTransition

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 isVisible was 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

Demo

You can find a working demo of this component here. Feel free to reuse it!

Disclaimer

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!

Read, see, play next
read7 min

Discovering ‘Moments that Matter’ for truly meaningful Data Design

Part of the C°F Data Design Toolkit

read7 min

Applying for a job as a digital designer (Visual / UX)

Useful tips for any applicant regardless of their seniority