There's a specific kind of bad animation I notice immediately: the count-up stat that stutters as it ticks, the progress bar that lags a frame behind your scroll, the "active" tab underline that snaps instead of glides. None of it is broken, exactly. It just feels cheap. And nine times out of ten, the cause is the same — the animation is being driven through React state, so every frame triggers a re-render, and the main thread can't keep up.

I build motion-heavy interfaces for a living, mostly in Next.js 16 and React 19, and I've landed on a small set of patterns that stay smooth because they bypass React's render loop entirely. They lean on Motion — the library formerly known as Framer Motion. It went independent and got renamed in 2025, so the package is now motion and the import you want is motion/react, not framer-motion (the APIs are identical, only the import path changed).

Here are three I reach for constantly, plus the reduced-motion discipline that should wrap all of them.

The mental model: MotionValues over state

The single idea that fixes most jank: a MotionValue is a value Motion tracks outside of React. When it changes, Motion updates the DOM directly via transform or opacity — it does not call setState, so your component doesn't re-render. That's the whole trick. A number ticking from 0 to 4,200 should touch the DOM ~60 times a second and re-render React zero times.