React Spring API Reference
Complete API documentation for React Spring hooks, components, and utilities.
Table of Contents
Core Hooks
useSpring
Create a single spring animation.
TypeScript Signature (Object Config):
function useSpring(config: SpringConfig): SpringValuesTypeScript Signature (Function Config):
function useSpring(
configFn: () => SpringConfig,
deps?: any[]
): [SpringValues, SpringRef]Parameters:
configorconfigFn- Animation configurationdeps- Dependency array for re-evaluation (function config only)
Returns:
- Object config:
SpringValuesfor rendering - Function config:
[SpringValues, SpringRef]tuple
Example (Object Config):
const springs = useSpring({
from: { opacity: 0 },
to: { opacity: 1 },
config: { tension: 170, friction: 26 }
})Example (Function Config):
const [springs, api] = useSpring(() => ({
from: { opacity: 0 },
config: { tension: 170, friction: 26 }
}), [])
// Trigger animation imperatively
api.start({ to: { opacity: 1 } })useSprings
Create multiple spring animations with a unified API.
TypeScript Signature (Object Config):
function useSprings(count: number, config: SpringConfig): SpringValues[]TypeScript Signature (Function Config):
function useSprings(
count: number,
configFn: (index: number) => SpringConfig,
deps?: any[]
): [SpringValues[], SpringRef]Parameters:
count- Number of springs to createconfigorconfigFn- Configuration (function receives index)deps- Dependency array for re-evaluation
Returns:
- Object config:
SpringValues[]array - Function config:
[SpringValues[], SpringRef]tuple
Example:
const springs = useSprings(
items.length,
items.map((item, i) => ({
from: { opacity: 0, x: -20 },
to: { opacity: 1, x: 0 },
delay: i * 100
}))
)useTrail
Create a trailing animation where each spring follows the previous.
TypeScript Signature (Object Config):
function useTrail(count: number, config: SpringConfig): SpringValues[]TypeScript Signature (Function Config):
function useTrail(
count: number,
configFn: () => SpringConfig,
deps?: any[]
): [SpringValues[], SpringRef]Example:
const trails = useTrail(5, {
from: { opacity: 0, x: -20 },
to: { opacity: 1, x: 0 },
config: config.gentle
})useTransition
Animate a dataset with enter/leave transitions.
TypeScript Signature (Object Config):
function useTransition<Item>(
data: Item[],
config: TransitionConfig<Item>
): TransitionFnTypeScript Signature (Function Config):
function useTransition<Item>(
data: Item[],
configFn: () => TransitionConfig<Item>,
deps?: any[]
): [TransitionFn, SpringRef]TransitionConfig Properties:
from- Initial styles for entering itemsenter- Target styles for entered itemsleave- Exit styles for leaving itemsupdate- Styles for items that update (optional)keys- Function or key to identify items
Example:
const transitions = useTransition(items, {
from: { opacity: 0, height: 0 },
enter: { opacity: 1, height: 80 },
leave: { opacity: 0, height: 0 },
keys: item => item.id
})
return transitions((style, item) => (
<animated.div style={style}>{item.text}</animated.div>
))useSpringValue
Create a single animated value.
TypeScript Signature:
function useSpringValue<T>(
initial: T,
config?: SpringConfig
): SpringValue<T>Example:
const opacity = useSpringValue(0, {
config: { mass: 2, friction: 5, tension: 80 }
})
// Update value
opacity.start(1)Utility Hooks
useScroll
Track scroll position with spring physics.
TypeScript Signature:
function useScroll(config?: ScrollConfig): {
scrollX: SpringValue<number>
scrollY: SpringValue<number>
scrollXProgress: SpringValue<number>
scrollYProgress: SpringValue<number>
}ScrollConfig Properties:
container- Scroll container ref (default: window)config- Spring configuration
Example:
const { scrollYProgress } = useScroll()
return (
<animated.div style={{ opacity: scrollYProgress }}>
Fades in as you scroll
</animated.div>
)useInView
Trigger animation when element enters viewport.
TypeScript Signature:
function useInView<T extends HTMLElement>(
configFn: () => SpringConfig,
options?: IntersectionObserverInit
): [RefCallback<T>, SpringValues]Options (IntersectionObserverInit):
root- Viewport element (default: browser viewport)rootMargin- Margin around root (e.g., '-40% 0%')threshold- Visibility threshold (0-1)
Example:
const [ref, springs] = useInView(
() => ({
from: { opacity: 0, y: 100 },
to: { opacity: 1, y: 0 }
}),
{ rootMargin: '-20% 0%' }
)
return <animated.div ref={ref} style={springs}>Content</animated.div>useSpringRef
Create a ref for controlling springs imperatively.
TypeScript Signature:
function useSpringRef(): SpringRefExample:
const api = useSpringRef()
const springs = useSpring({
ref: api,
from: { opacity: 0 },
to: { opacity: 1 }
})
// Control via ref
api.start({ opacity: 0.5 })useIsomorphicLayoutEffect
Cross-platform useLayoutEffect (server-safe).
TypeScript Signature:
function useIsomorphicLayoutEffect(
effect: EffectCallback,
deps?: DependencyList
): voidUsage:
Use like useLayoutEffect but works on server-side rendering.
Components
animated
Higher-Order Component to make elements animatable.
Built-in Animated Components:
import { animated } from '@react-spring/web'
animated.div
animated.span
animated.p
animated.svg
animated.path
animated.g
// ... all HTML elementsCustom Component Animation:
import { animated } from '@react-spring/web'
import { CustomComponent } from './CustomComponent'
const AnimatedCustom = animated(CustomComponent)
// Component must forward style prop to native element
function CustomComponent({ style, ...props }) {
return <div style={style} {...props} />
}Three.js Integration:
import { animated } from '@react-spring/three'
import { MeshDistortMaterial } from '@react-three/drei'
const AnimatedMaterial = animated(MeshDistortMaterial)Configuration
Config Presets
Pre-defined spring configurations for common animation feels.
import { config } from '@react-spring/web'
config.default // { tension: 170, friction: 26 }
config.gentle // { tension: 120, friction: 14 }
config.wobbly // { tension: 180, friction: 12 }
config.stiff // { tension: 210, friction: 20 }
config.slow // { tension: 280, friction: 60 }
config.molasses // { tension: 280, friction: 120 }Usage:
useSpring({
from: { x: 0 },
to: { x: 100 },
config: config.wobbly
})Config Properties
Fine-tune spring physics manually.
SpringConfig Interface:
interface SpringConfig {
mass?: number // Mass of object (default: 1)
tension?: number // Spring strength (default: 170)
friction?: number // Opposing force (default: 26)
clamp?: boolean // Prevent overshooting (default: false)
precision?: number // Stop threshold (default: 0.0001)
velocity?: number // Initial velocity (default: 0)
duration?: number // Override physics with fixed duration
easing?: EasingFunction // Easing function (requires duration)
bounce?: number // Bounce factor 0-1 (alternative to tension/friction)
}Property-Specific Config:
useSpring({
x: 100,
y: 200,
config: {
x: { tension: 300, friction: 20 }, // Fast horizontal
y: { tension: 100, friction: 30 } // Slow vertical
}
})Config as Function:
useSpring({
x: 100,
scale: 1.5,
config: (key) => {
if (key === 'scale') return { mass: 4, friction: 10 }
return config.default
}
})API Methods
SpringRef API
Imperative control interface returned by function-config hooks.
Methods:
api.start(config)
Start or update animation.
api.start({
from: { x: 0 },
to: { x: 100 },
config: { tension: 200 },
onRest: () => console.log('Done!')
})api.pause()
Pause all animations.
api.pause()api.resume()
Resume paused animations.
api.resume()api.stop()
Stop all animations immediately.
api.stop()api.set(values)
Instantly set values without animating.
api.set({ x: 100, opacity: 1 })SpringValue Methods
Methods available on individual SpringValue instances.
get() - Get current value:
const currentX = springs.x.get()getVelocity() - Get current velocity:
const velocity = springs.x.getVelocity()to() - Transform value:
<animated.div
style={{
transform: springs.x.to(x => `translateX(${x}px)`)
}}
/>start() - Animate this value:
springs.opacity.start(1)Events
Event callbacks for animation lifecycle.
Event Properties:
interface AnimationProps {
onStart?: (result: AnimationResult) => void
onChange?: (result: AnimationResult) => void
onRest?: (result: AnimationResult) => void
onPause?: () => void
onResume?: () => void
}Global Events:
useSpring({
x: 100,
onStart: () => console.log('Animation started'),
onRest: () => console.log('Animation completed')
})Key-Specific Events:
useSpring({
x: 100,
y: 200,
onStart: {
x: () => console.log('x started'),
y: () => console.log('y started')
}
})Globals
Global configuration for all animations.
Globals.assign(config):
import { Globals } from '@react-spring/web'
// Skip all animations (accessibility)
Globals.assign({ skipAnimation: true })
// Custom frame loop
Globals.assign({ frameLoop: 'always' }) // or 'demand'
// Custom performance now
Globals.assign({ now: () => performance.now() })Common Use Cases:
// Prefers reduced motion
useEffect(() => {
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)')
Globals.assign({ skipAnimation: mediaQuery.matches })
}, [])
// Testing mode
if (process.env.NODE_ENV === 'test') {
Globals.assign({ skipAnimation: true })
}Advanced Patterns
Chaining Animations
const springs = useSpring({
from: { x: 0, background: '#ff6d6d' },
to: [
{ x: 100, background: '#fff59a' },
{ x: 0, background: '#88DFAB' }
],
loop: true
})Async to Function
const springs = useSpring({
from: { x: 0 },
to: async (next) => {
await next({ x: 100 })
await next({ x: 50 })
await next({ x: 0 })
}
})Conditional Animation
const [springs, api] = useSpring(() => ({
x: 0
}), [])
useEffect(() => {
if (condition) {
api.start({ x: 100 })
} else {
api.start({ x: 0 })
}
}, [condition])Interpolation
<animated.div
style={{
transform: springs.x.to({
range: [0, 0.5, 1],
output: ['translateX(0px)', 'translateX(50px)', 'translateX(100px)']
})
}}
/>Performance Tips
- Use function config for imperative control - Avoids recreation on render
- Set appropriate precision - Higher values reduce updates
- Batch similar animations - Use
useSpringsfor multiple similar items - Skip animations in tests - Use
Globals.assign({ skipAnimation: true }) - Avoid animating layout - Prefer transforms and opacity
- Use
immediatefor instant changes -api.start({ x: 100, immediate: true })
TypeScript Support
React Spring is fully typed. Key interfaces:
import type {
SpringValue,
SpringValues,
SpringRef,
SpringConfig,
AnimationResult
} from '@react-spring/web'Typing Custom Animations:
interface MySpringValues {
x: number
opacity: number
color: string
}
const springs = useSpring<MySpringValues>({
from: { x: 0, opacity: 0, color: '#fff' },
to: { x: 100, opacity: 1, color: '#000' }
})