Skip to Content

React

The sprungdesign/react adapter is a single hook, useSpring. It wraps the core controller and re-renders your component with the live value each frame.

npm install sprungdesign

React is an optional peer dependency (17+); installing sprungdesign doesn’t pull in React.

useSpring(target, config?)

import { useSpring } from "sprungdesign/react"; function Box({ open }: { open: boolean }) { const x = useSpring(open ? 200 : 0, { stiffness: 320, damping: 14 }); return <div style={{ transform: `translateX(${x}px)` }} />; }
  • It returns a number you render directly.
  • The value starts at target on mount — there’s no entrance animation. If you want one, mount with one target and change it (e.g. in an effect).
  • When target changes, it retargets velocity-continuously — interrupt an in-flight animation and it never jumps.

Config is read once

config is read a single time, when the underlying controller is created. Changing it across renders is a no-op. Pass a stable feel:

// ✅ stiffness/damping fixed for the life of the component const x = useSpring(target, { stiffness: 320, damping: 14 }); // ❌ this won't switch feel — the second config is ignored const x = useSpring(target, fast ? presetA : presetB);

If you genuinely need to swap physics at runtime, remount the component with a key, or drop down to the core spring() controller and recreate the handle yourself.

Reduced motion

useSpring honors prefers-reduced-motion: when the user has it enabled, the value snaps to the target instead of animating. The preference is evaluated at each retarget, not tracked live — so a user who toggles it mid-animation sees the new behavior on the next target change.

Server rendering & StrictMode

  • SSR-safe — returns target on the server and the first client render, so hydration matches. Nothing touches the DOM at import.
  • StrictMode / concurrent-safe — the double-invocation and effect remounting that StrictMode does won’t desync the animation.

Animating multiple values

useSpring animates one number. Call it once per dimension:

function Card({ active }: { active: boolean }) { const scale = useSpring(active ? 1.05 : 1, { stiffness: 260, damping: 18 }); const lift = useSpring(active ? -8 : 0, { stiffness: 260, damping: 18 }); return ( <div style={{ transform: `translateY(${lift}px) scale(${scale})` }} /> ); }

Next steps

Last updated on