Playing with animations and React useState

Hemant Bhatt
4 min readMay 14, 2021

In this article, I will show you how I orchestrated the below shown animations in React :-

A gif showing animated webpage built with react

For better clarity as to what keyframes are being animated, let me show you the above animation in slow-motion below:

gif showing same animation in slow-motion

Every button click has two keyframes. Its starts by taking the last selected flavour out of the viewport and then ends by putting the newly selected flavour inside the viewport.

To nail this animation we just need to use just 2 things, the first is the useState hook from React and the second is a animation library called anime.js.

So lets start with the 3 buttons on the right hand side of our website because they are directly connected to the animation keyframes. The styling of the 3 buttons and the ice-cream keyframe is dependent on the below state:

const [button,setButton]=useState(-1);

And the JSX for the buttons look something like this:

<button className={getClass(1)}onClick={()=>{startSeq(1)}}>
Blueberry
</button>
<button className={getClass(2)} onClick={()=>{startSeq(2)}}>
Vanilla
</button>
<button className={getClass(3)} onClick={()=>{startSeq(3)}}>
Strawberry
</button>

I will leave the CSS styling of the buttons on you for active and inactive states.

Below you can look at the different style classes that are being returned based on the id from the getClass function. This function lets us differentiate between selected and unselected button styles.

Now that the styling of the buttons are out of the way we can focus on the onClick event of each button which triggers the startSeq function. Here startSeq function does two things:

  1. Sets the button state to the clicked button
  2. Performs the animation keyframes
const startSeq=(id)=>{//1. Button state set to id
setButton(id);
//2. Animation keyframes
anime({});
}

Lets move on to the animations then:

Notice that there are 4 Div elements in play here:

bifurcation of different div elements

The class with “cream” name has a number at its end which helps in animating it with respect to the button class.

All 3 cream divs are above the viewport in the beginning when the site is loaded, and they are animated inside the viewport once their respective buttons are clicked.

cream div outside the viewport

Here I positioned both the hand and the cream div as “absolute” inside a box.

All divs absolutely positioned

Here I also noticed that for the absolute box, the cream div rests perfectly above the cone at 55% from the bottom. To throw the cream outside the viewport I needed to set it’s bottom property to 130%. So now we know that the cream div must alternate between ‘bottom:130%’ and ‘bottom:55%’ property. Initially we will set it to 130%, which means outside(or above) the viewport.

Now the animation can be further broken down into two different actions right after a flavour button is clicked:

  1. Previously selected cream flavour goes outside the viewport.
  2. Current cream flavour slides into the viewport.

So now here is how our startSeq function will look like:

//Here id is the current button state selectedconst startSeq=(id)=>{//Animate the creamN div outside the viewport
//where N is the previous button state
// Button state set to id(i.e the new button state)
setButton(id);
//Animate the creamX div inside the viewport
//where X is id (i.e the new button state)
}

So now when we fill the comments with actual code using anime.js, a JavaScript animation library, it will look something like below:

Here the anime() function is used to trigger the keyframe animations and since these are keyframes, you can add more subtlety to your animations by adding more items to the keyframes array.

keyframes: [{ bottom: '58%' },
{ bottom: '55%'}
]

You can tweak your animations even further by using the complete() callback inside the anime() function like the following:

--

--