Performant “Scroll Animation” in React with React UI Animate

Dipesh Rai
3 min readSep 21, 2021

In my previous post, Intro to “Scroll Animation” in React with React UI Animate, I talked about how to implement scroll animation in React. But with larger nested components, using State for scroll animation is costly and has performance issues. Therefore, In this post I am going to show how we can implement a scroll animation without using State. Let’s dive into it.


Final animation we are going to make


Just run the following code inside your react project with npm

npm i react-ui-animate

or you could use yarn

yarn add react-ui-animate

Basic Concept



Here, I have created a div which is fixed positioned with 100% width and 100% height and a rectangular div inside it is centered with flex. And I have used a div of height 2000px to make the document scrollable.

We already used the useScroll() hook and interpolate() function in our previous post. You can check it out here.


To understand the basic concept of animation, you should understand the useAnimatedValue() hook first which is provided by react-ui-animate.

const animationNode = useAnimatedValue(initialValue)

useAnimatedValue() returns an animation node whose .value property is initialized to the passed argument initialValue.

Rather than using state for storing the scrollY value from useScroll() hook, we use useAnimatedValue() to store scrollY position. The main reason behind using useAnimatedValue() instead of state is that the component is not re-rendered when the value changes hence, providing you the performance with no issue.

We can do it by

const y = useAnimatedValue(0);useScroll(({ scrollY }) => {
y.value = scrollY;

We created an animation node y which has .value property and we assigned the scrollY value from useScroll() hook to y animation node. Whenever we scroll the document, the value of scrollY is assigned to y.value for every pixel. Let us use this y.value to manipulate different properties of an element using interpolation.

const size = interpolate(y.value, [0, 500], [100, 400], { extrapolate: “clamp” });

We are interpolating the y.value from input range 0–500 to output range [100, 400] i.e. If we scroll the document from 0px to 500px, then the size will be changing from 100px to 400px.

So, Now we have created an animation node. Let’s apply this animation node to a div.


div cannot read this special animation node from useAnimatedValue() hook, for that we will use the AnimatedBlock component provided by react-ui-animate which inherits all properties of a div as well as animation values.

Let’s apply a size to AnimatedBlock.



Similarly we can interpolate the border radius

const borderRadius = interpolate(y.value, [0, 500], [“50%”, “10%”], { extrapolate: “clamp” });



As you can notice, after the animation is applied, the transition of an object is smooth. If you don’t want a smooth transition then you can add an object { immediate: true } as the second argument of useAnimatedValue().

const y = useAnimatedValue(0, { immediate: true });



Live Demo

That’s all for the performant scroll animation.

You can check out live example at

You can follow me on github:

If you enjoyed this article, please recommend and share it! Thanks for your time.

Dipesh Rai

Codniv Innovations Pvt. Ltd.



Dipesh Rai

Co-founder at Codniv, JavaScript enthusiast 🙌, Front-end engineer💻