Why I use React-Spring
In this article, we will be looking at an outstanding library called React Spring which makes it super easy to control component based animations. And yes, before you ask, it does support hooks which can turn any data into animated data, with a single line.
What is React Spring?
The whole point of using React Spring is to give you the upper hand in animations by providing you with a better experience as well as faster delivery with incredible performance.
Quotes from the introduction section on the official website:
react-spring is a spring-physics based animation library that should cover most of your UI related animation needs. It gives you tools flexible enough to confidently cast your ideas into moving interfaces.
It inherits animated’s powerful interpolations and performance, as well as react-motion’s ease of use. But while animated is mostly imperative and react-motion mostly declarative, react-spring bridges both. You will be surprised how easy static data is cast into motion with small, explicit utility functions that don’t necessarily affect how you form your views.
If you want to understand about the differences of imperative vs declarative programming in this link.
Using physics we no longer need to consider Duration or Easing Curves. Instead, we focus on actual physical properties. React Spring heavily uses this logic on all its animations which is why it is said to work like any other real-world property.
Confused? Imagine you are throwing a ball vertically downwards from a building, the ball won’t ask you about the time after which it should hit the bottom, right? Rather, we would let physics do the talking. Same applies to React Spring.
The Use Case
React Spring comes with some utility functions. Let’s see a use case that demonstrates how simple is it to use. Let’s use a real life example I have recently faced.
Assume we have a React Native project and in it we want to render a menu with items. Each item once the item is rendered, it should animate its’ entrance from one direction to another while on the same time the opacity changes.
Before we start using React Spring, let’s first use React Native.
We want to be performant - so, we will use useNativeDriver property for the animation, which tells React Native to handle outside the JS thread.
Now we face couple of issues
- Animation properties. We are not able to animate the width property. We have to stick to the abilities provided by Animated.View which are Transform based (Scale, Translate, Rotate etc) and not Shape based (Width, Height etc). Note that in this simple example it’s still fine, we can certainty use translate-x to animate the desired effect. However, when we face a more complex animations it might not be the case.
- Developer Experience (DX). While the User Experience (UX) is simple and elegant, by using the native animation code, we add more complex code which makes it hard to read and understand.
React Spring to the rescue
Now we re-write out Item component using React Spring. Let’s see how it helps us resolve the issues mentioned earlier.
We can now examine the differences:
1. Developer Experience (DX).
See ho much cleaner the API is? Even without knowing how useSpring hook works and what it returns you can easily read the component code and guess.
One way of working with useSpring hook is to provide it with an object, while the other way is to provide it with a function. Based on the input provided to useSpring, the returned value is provided for us to use.
Let’s see an example:
Back to the Item component, we do not care for the duration of the animation, we don’t care of when it starts, we just want to it to animate & get the job done. So in this case we use the first way pattern.
2. Animation properties
Notice that now we are not bound the properties supported on Animated from React Native (scale, translate, etc). We can animate any property of style we want (width, left, etc) and let React-Spring handle it for us.
Cross Platform
Eh? What do you mean by that?
I don’t mean iOS or Android, well yes, it will work on both, that’s not it.
Well it turns out that if we read Item Component the code again, we are not actually bound to the environment. Yes, we do use View & TouchableOpacity components but regarding the animation part, it does not involve any environment bounding.
Ideally, we may use the same code for the animation with no changes to it at all. The only changes required are for another target environment are the nodes used. See the following example that uses the DOM with the same animations we defined earlier.
Since react-spring uses dependency injections internally, it can compile to multiple platforms.
- Web (react-spring)
- React Native (react-spring/native)
- Canvas (react-spring/konva) [HTML5 Canvas]
- WebGL (react-spring/three) [Works great with react-three-fiber, that uses ThreeJS with React]
This way if we re-use the animations logic on different targets.
That’s it
I want you to keep in mind that some more complex animations would be easier to implement using react-native-reanimated package. However if you are just looking for a small animation react-spring is a great solution.
All & all I hope I’ve convinced you to consider using react-spring in the feature. You can read more about it on their website. They have a lot of complex examples for you to explore
Thanks for reading✌️. Stay safe😷!