Ever since i started developing i was fascinated by the vividness of animated applications, they felt alive. And we sure have come a long way, too. There are dozens of tools to choose from today. From tweening libraries to full fledged declarative options, especially in the React world.

The prevalent options today are react-motion, animated, react-move, popmotion and a couple of others. All of them have incorporated incredible ideas over time, some have changed the way we think of implementing movement. I would primarily like to credit react-motion for that in particular.

React-motion changed everything

Polar opposites

In practice however things were not always so bright as the freedom of dom-oriented tweening tools has often been lost in translation. Despite the many merits, some of these libraries had shortcomings that were hard to overlook, some could not interpolate data for instance, were complex and unwieldy, a bit slow as they would let React render each frame of the animation, or lacked declarative components, which meant managing loose-end animation handles.

One day it struck me that the time i have been putting into working around animation related troubles could perhaps be spent bringing them together, befriending them so to say. That day react-spring was born.

What makes it so different then?

React-spring is based on a cooked down, simplified animated fork. You may know animated from react-native already, and if not check out the following slides in which Christopher Chedeau explains how it works.

Animated brought performance back into the React animation game

It was turned into a barebones foundation that now drives lean and inexpensive building blocks or primitives. This combination of a rock solid low-level foundation with all its benefits and declarative abstractions becomes extremely valuable as it lends to an eco system of modular building blocks.

Such primitives could do just about anything. One shifts data from here to there, one trails, one transitions between lifecycle changes, one parallaxes pages, one orchestrates, and so on.

Transitions as we would normally think of them

This stuff is not so hard in react-spring at all

At the same time the focus is on absolute simplicity. Things that would usually get hairy as you are shaping your code around a library’s specific demands can be done in a couple of lines now without warping the data at all.

The most trivial implementation however can only go so far and complex use-cases demand fine control. React-spring’s premise is: simplicity first, but its properties are flexible enough to support both simple and complex use-cases.

Can it interpolate?

Oh yes it can. It will move effortlessly between most of the webs units, from colors, percentages, arrays, vectors, lenghts, SVG paths, and so on. This means you can animate actual, non-numeric data. There are also means for ranges, clamping, and custom interpolators.

What about performance?

Letting React render frames chokes the CPU (react-motion/move, etc.)

Animating outside of React via requestAnimationFrame (animated, react-spring)

One of the strengths of animated is that it can apply animations natively without relying on React to render updates frame by frame like virtually all other React animation libraries do. React-spring thereby benefits from animated’s clever rendering model.

The difference may not be apparent in simple situations, but try a nested chart and React will plow through the CPU, choking the browsers frame budget.

Applying updates outside of React has strict limits as you can only animate dom-native styles and attributes since generic React components do not have a representation in the dom, but here you can choose between both models by supplying the native flag.

Animated is equipped to handle full-native drivers as well, so in the future, should web animations gain more support, it would even be possible to do all the animation in the compositor thread. But for now react-spring can be compared to gsap or d3, which animate in a requestAnimationFrame loop as well.

Are declarative primitives really enough?

For most UI related tasks, maybe, but for anything that involves staging and orchestration — it probably isn’t enough.

The lack of imperative animation can sometimes hurt, and one of the hardest bits in most of the libraries today is switching between primitives, for instance moving something with a spring first, trailing its elements into place, then transition additions and removals. As you can imagine, doing this declaratively is almost futile as it would mean slicing and dicing the heck out of your code. This is where traditional tweening libraries shine.

While it is still highly experimental at the moment, react-spring already seeks ways to blend scripting and composition, which might offer more freedom when it comes to chaining and orchestration.