0
# Animation Hooks
1
2
React hooks for declarative animation control including springs, transitions, trails, and utility hooks. These hooks provide the core animation functionality for @react-spring/web.
3
4
## Capabilities
5
6
### useSpring
7
8
Creates a single spring animation with configurable properties and easing.
9
10
```typescript { .api }
11
/**
12
* Creates a single spring animation
13
* @param props - Spring configuration and target values
14
* @returns Spring values for use in animated components
15
*/
16
function useSpring<Props extends object>(
17
props: UseSpringProps<Props>
18
): SpringValues<PickAnimated<Props>>;
19
20
/**
21
* Creates a spring with function-based props and dependencies
22
* @param props - Function returning spring configuration
23
* @param deps - Dependency array for recalculation
24
* @returns Tuple of spring values and spring ref
25
*/
26
function useSpring<Props extends object>(
27
props: () => UseSpringProps<Props>,
28
deps?: readonly any[]
29
): [SpringValues<PickAnimated<Props>>, SpringRef<PickAnimated<Props>>];
30
31
interface UseSpringProps<Props extends object = any> extends ControllerUpdate<PickAnimated<Props>> {
32
/** Reference for imperative control */
33
ref?: SpringRef<PickAnimated<Props>>;
34
}
35
```
36
37
**Usage Examples:**
38
39
```typescript
40
import { useSpring, animated } from "@react-spring/web";
41
42
// Basic spring animation
43
function FadeIn() {
44
const styles = useSpring({
45
from: { opacity: 0 },
46
to: { opacity: 1 },
47
config: { duration: 1000 }
48
});
49
50
return <animated.div style={styles}>Content</animated.div>;
51
}
52
53
// Function-based with dependencies
54
function ConditionalSpring({ show }) {
55
const [styles, api] = useSpring(() => ({
56
opacity: show ? 1 : 0,
57
transform: show ? 'translateY(0px)' : 'translateY(-50px)'
58
}), [show]);
59
60
return <animated.div style={styles}>Conditional content</animated.div>;
61
}
62
```
63
64
### useSprings
65
66
Creates multiple spring animations with individual configurations.
67
68
```typescript { .api }
69
/**
70
* Creates multiple spring animations
71
* @param length - Number of springs to create
72
* @param props - Configuration for each spring
73
* @returns Array of spring values
74
*/
75
function useSprings<Props extends object>(
76
length: number,
77
props: UseSpringProps<Props>[] | ((index: number) => UseSpringProps<Props>)
78
): SpringValues<PickAnimated<Props>>[];
79
80
/**
81
* Creates multiple springs with function-based props and dependencies
82
* @param length - Number of springs to create
83
* @param props - Function returning spring configurations
84
* @param deps - Dependency array for recalculation
85
* @returns Tuple of spring values array and spring ref
86
*/
87
function useSprings<Props extends object>(
88
length: number,
89
props: () => UseSpringProps<Props>[] | ((index: number) => UseSpringProps<Props>),
90
deps?: readonly any[]
91
): [SpringValues<PickAnimated<Props>>[], SpringRef<PickAnimated<Props>>];
92
```
93
94
**Usage Examples:**
95
96
```typescript
97
// Multiple springs with different configs
98
function MultipleBoxes({ items }) {
99
const springs = useSprings(items.length, items.map((item, index) => ({
100
from: { opacity: 0, transform: 'translateX(-100px)' },
101
to: { opacity: 1, transform: 'translateX(0px)' },
102
delay: index * 100,
103
})));
104
105
return springs.map((styles, index) => (
106
<animated.div key={index} style={styles}>
107
{items[index]}
108
</animated.div>
109
));
110
}
111
```
112
113
### useTrail
114
115
Creates staggered spring animations that follow each other in sequence.
116
117
```typescript { .api }
118
/**
119
* Creates staggered spring animations
120
* @param length - Number of items in the trail
121
* @param props - Spring configuration applied to all items
122
* @returns Array of spring values with staggered timing
123
*/
124
function useTrail<Props extends object>(
125
length: number,
126
props: UseTrailProps<Props>
127
): SpringValues<PickAnimated<Props>>[];
128
129
/**
130
* Creates trail with function-based props and dependencies
131
* @param length - Number of items in the trail
132
* @param props - Function returning spring configuration
133
* @param deps - Dependency array for recalculation
134
* @returns Tuple of spring values array and spring ref
135
*/
136
function useTrail<Props extends object>(
137
length: number,
138
props: () => UseTrailProps<Props>,
139
deps?: readonly any[]
140
): [SpringValues<PickAnimated<Props>>[], SpringRef<PickAnimated<Props>>];
141
142
type UseTrailProps<Props extends object = any> = UseSpringProps<Props>;
143
```
144
145
**Usage Examples:**
146
147
```typescript
148
// Staggered list animation
149
function StaggeredList({ words }) {
150
const trails = useTrail(words.length, {
151
from: { opacity: 0, transform: 'translateY(20px)' },
152
to: { opacity: 1, transform: 'translateY(0px)' },
153
});
154
155
return trails.map((styles, index) => (
156
<animated.div key={index} style={styles}>
157
{words[index]}
158
</animated.div>
159
));
160
}
161
```
162
163
### useTransition
164
165
Animates list transitions with enter, update, and leave phases.
166
167
```typescript { .api }
168
/**
169
* Animates list transitions with enter/update/leave phases
170
* @param data - Array of items to transition
171
* @param props - Transition configuration
172
* @returns Transition function for rendering items
173
*/
174
function useTransition<Item, Props extends object>(
175
data: OneOrMore<Item>,
176
props: UseTransitionProps<Item, Props>
177
): TransitionFn<Item, PickAnimated<Props>>;
178
179
/**
180
* Creates transition with function-based props and dependencies
181
* @param data - Array of items to transition
182
* @param props - Function returning transition configuration
183
* @param deps - Dependency array for recalculation
184
* @returns Tuple of transition function and spring ref
185
*/
186
function useTransition<Item, Props extends object>(
187
data: OneOrMore<Item>,
188
props: () => UseTransitionProps<Item, Props>,
189
deps?: readonly any[]
190
): [TransitionFn<Item, PickAnimated<Props>>, SpringRef<PickAnimated<Props>>];
191
192
interface UseTransitionProps<Item, Props extends object = any> {
193
/** Animation when items enter */
194
from?: TransitionTo<Item, PickAnimated<Props>>;
195
/** Animation when items first appear or update */
196
enter?: TransitionTo<Item, PickAnimated<Props>>;
197
/** Animation when items update */
198
update?: TransitionTo<Item, PickAnimated<Props>>;
199
/** Animation when items leave */
200
leave?: TransitionTo<Item, PickAnimated<Props>>;
201
/** Key function for item identification */
202
keys?: ItemKeys<Item>;
203
/** Animation configuration */
204
config?: SpringConfig | ((item: Item, state: string) => SpringConfig);
205
/** Delay before animation starts */
206
delay?: number;
207
/** Animation trail delay between items */
208
trail?: number;
209
}
210
211
type TransitionFn<Item, State extends Lookup> = (
212
style: SpringValues<State>,
213
item: Item,
214
transition: TransitionState<Item>,
215
index: number
216
) => React.ReactElement;
217
```
218
219
**Usage Examples:**
220
221
```typescript
222
// List transitions
223
function TodoList({ todos }) {
224
const transitions = useTransition(todos, {
225
from: { opacity: 0, height: 0 },
226
enter: { opacity: 1, height: 'auto' },
227
leave: { opacity: 0, height: 0 },
228
keys: todo => todo.id,
229
});
230
231
return transitions((style, todo) => (
232
<animated.div style={style}>
233
{todo.text}
234
</animated.div>
235
));
236
}
237
238
// Modal transitions
239
function Modal({ show, children }) {
240
const transitions = useTransition(show, {
241
from: { opacity: 0, transform: 'scale(0.9)' },
242
enter: { opacity: 1, transform: 'scale(1)' },
243
leave: { opacity: 0, transform: 'scale(0.9)' },
244
});
245
246
return transitions((style, item) =>
247
item ? (
248
<animated.div style={style}>
249
{children}
250
</animated.div>
251
) : null
252
);
253
}
254
```
255
256
### useChain
257
258
Chains multiple spring animations to run in sequence.
259
260
```typescript { .api }
261
/**
262
* Chains multiple spring animations to run in sequence
263
* @param refs - Array of spring refs to chain
264
* @param timeSteps - Optional timing for each animation (0-1)
265
* @param timeFrame - Total duration for the entire chain
266
*/
267
function useChain(
268
refs: SpringRef[],
269
timeSteps?: number[],
270
timeFrame?: number
271
): void;
272
```
273
274
**Usage Examples:**
275
276
```typescript
277
function ChainedAnimation() {
278
const [open, setOpen] = useState(false);
279
280
const [fadeStyles, fadeApi] = useSpring(() => ({
281
opacity: open ? 1 : 0
282
}), []);
283
284
const [scaleStyles, scaleApi] = useSpring(() => ({
285
transform: open ? 'scale(1)' : 'scale(0)'
286
}), []);
287
288
// Chain fade first, then scale
289
useChain(open ? [fadeApi, scaleApi] : [scaleApi, fadeApi], [0, 0.5], 1000);
290
291
return (
292
<animated.div style={fadeStyles}>
293
<animated.div style={scaleStyles}>
294
Chained animation
295
</animated.div>
296
</animated.div>
297
);
298
}
299
```
300
301
### useSpringRef
302
303
Creates a reference for imperative control of spring animations.
304
305
```typescript { .api }
306
/**
307
* Creates a reference for imperative spring control
308
* @returns Spring reference for imperative API calls
309
*/
310
function useSpringRef<State extends Lookup = Lookup>(): SpringRef<State>;
311
```
312
313
### useSpringValue
314
315
Creates a single animated value that can be used independently.
316
317
```typescript { .api }
318
/**
319
* Creates a single animated value
320
* @param initialValue - Initial value for the spring
321
* @param props - Optional spring configuration
322
* @returns SpringValue instance
323
*/
324
function useSpringValue<T>(
325
initialValue: T,
326
props?: SpringUpdate<T>
327
): SpringValue<T>;
328
```
329
330
**Usage Examples:**
331
332
```typescript
333
function IndependentValue() {
334
const opacity = useSpringValue(0, { config: { tension: 300 } });
335
336
const handleClick = () => {
337
opacity.start(opacity.get() === 0 ? 1 : 0);
338
};
339
340
return (
341
<animated.div
342
style={{ opacity }}
343
onClick={handleClick}
344
>
345
Click to toggle
346
</animated.div>
347
);
348
}
349
```
350
351
### Utility Hooks
352
353
Additional hooks for specific use cases.
354
355
```typescript { .api }
356
/**
357
* Creates scroll-based animations
358
* @param props - Scroll animation configuration
359
* @returns Spring values responding to scroll events
360
*/
361
function useScroll(props?: UseScrollProps): SpringValues<ScrollData>;
362
363
/**
364
* Creates resize-based animations
365
* @param props - Resize animation configuration
366
* @returns Spring values responding to resize events
367
*/
368
function useResize(props?: UseResizeProps): SpringValues<ResizeData>;
369
370
/**
371
* Creates intersection observer-based animations
372
* @param props - InView animation configuration
373
* @returns Tuple of spring values and ref to observe
374
*/
375
function useInView(props?: UseInViewProps): [SpringValues<InViewData>, React.RefObject<Element>];
376
```
377
378
## Declarative Components
379
380
React components providing declarative alternatives to animation hooks.
381
382
### Spring Component
383
384
Declarative component for single spring animations using render props pattern.
385
386
```typescript { .api }
387
/**
388
* Declarative spring animation component
389
* @param props - Spring configuration with children render prop
390
* @returns JSX element from children function
391
*/
392
function Spring<State extends object>(
393
props: SpringComponentProps<State>
394
): JSX.Element | null;
395
396
interface SpringComponentProps<State extends object> extends UseSpringProps<State> {
397
/** Render prop function receiving spring values */
398
children: (values: SpringValues<State>) => React.JSX.Element | null;
399
}
400
```
401
402
**Usage Examples:**
403
404
```typescript
405
import { Spring } from "@react-spring/web";
406
407
function DeclarativeSpring() {
408
return (
409
<Spring
410
from={{ opacity: 0 }}
411
to={{ opacity: 1 }}
412
config={{ duration: 1000 }}
413
>
414
{styles => <div style={styles}>Animated content</div>}
415
</Spring>
416
);
417
}
418
```
419
420
### Trail Component
421
422
Declarative component for staggered trail animations using render props pattern.
423
424
```typescript { .api }
425
/**
426
* Declarative trail animation component
427
* @param props - Trail configuration with children render prop
428
* @returns JSX element from children function
429
*/
430
function Trail<State extends object>(
431
props: TrailComponentProps<State>
432
): JSX.Element | null;
433
434
interface TrailComponentProps<State extends object> extends UseTrailProps<State> {
435
/** Number of items in the trail */
436
length: number;
437
/** Render prop function receiving array of spring values */
438
children: (values: SpringValues<State>[]) => React.JSX.Element | null;
439
}
440
```
441
442
**Usage Examples:**
443
444
```typescript
445
import { Trail } from "@react-spring/web";
446
447
function DeclarativeTrail({ items }) {
448
return (
449
<Trail
450
length={items.length}
451
from={{ opacity: 0, transform: 'translateY(20px)' }}
452
to={{ opacity: 1, transform: 'translateY(0px)' }}
453
>
454
{trails => (
455
<div>
456
{trails.map((style, index) => (
457
<div key={index} style={style}>
458
{items[index]}
459
</div>
460
))}
461
</div>
462
)}
463
</Trail>
464
);
465
}
466
```
467
468
### Transition Component
469
470
Declarative component for list transitions using render props pattern.
471
472
```typescript { .api }
473
/**
474
* Declarative transition animation component
475
* @param props - Transition configuration with children render prop
476
* @returns JSX element from children function
477
*/
478
function Transition<Item, State extends object>(
479
props: TransitionComponentProps<Item, State>
480
): JSX.Element | null;
481
482
interface TransitionComponentProps<Item, State extends object> extends UseTransitionProps<Item, State> {
483
/** Array of items to transition */
484
items: OneOrMore<Item>;
485
/** Render prop function receiving transition function */
486
children: (transitionFn: TransitionFn<Item, State>) => React.JSX.Element | null;
487
}
488
```
489
490
**Usage Examples:**
491
492
```typescript
493
import { Transition } from "@react-spring/web";
494
495
function DeclarativeTransition({ todos }) {
496
return (
497
<Transition
498
items={todos}
499
from={{ opacity: 0, height: 0 }}
500
enter={{ opacity: 1, height: 'auto' }}
501
leave={{ opacity: 0, height: 0 }}
502
keys={todo => todo.id}
503
>
504
{transitions => (
505
<div>
506
{transitions((style, todo) => (
507
<div style={style}>{todo.text}</div>
508
))}
509
</div>
510
)}
511
</Transition>
512
);
513
}
514
```
515
516
### useScroll
517
518
Creates scroll-linked animations that respond to window or element scroll position.
519
520
```typescript { .api }
521
/**
522
* Creates scroll-linked animations
523
* @param options - Configuration including optional container ref
524
* @returns Spring values with scroll progress and position
525
*/
526
function useScroll(
527
options?: UseScrollOptions
528
): SpringValues<{
529
scrollX: number;
530
scrollY: number;
531
scrollXProgress: number;
532
scrollYProgress: number;
533
}>;
534
535
interface UseScrollOptions extends Omit<SpringProps, 'to' | 'from'> {
536
/** Container element to observe (defaults to window) */
537
container?: MutableRefObject<HTMLElement>;
538
}
539
```
540
541
**Usage Examples:**
542
543
```typescript
544
import { useScroll, animated } from "@react-spring/web";
545
546
// Window scroll progress
547
function ScrollIndicator() {
548
const { scrollYProgress } = useScroll();
549
550
return (
551
<animated.div
552
style={{
553
transform: scrollYProgress.to(y => `scaleX(${y})`)
554
}}
555
/>
556
);
557
}
558
559
// Element scroll tracking
560
function ScrollContainer() {
561
const containerRef = useRef<HTMLDivElement>(null);
562
const { scrollY } = useScroll({ container: containerRef });
563
564
return (
565
<div ref={containerRef} style={{ height: 300, overflow: 'auto' }}>
566
<animated.div style={{ transform: scrollY.to(y => `translateY(${y}px)`) }}>
567
Scroll content
568
</animated.div>
569
</div>
570
);
571
}
572
```
573
574
### useResize
575
576
Creates animations based on element or window resize events.
577
578
```typescript { .api }
579
/**
580
* Creates resize-responsive animations
581
* @param options - Configuration including optional container ref
582
* @returns Spring values with width and height
583
*/
584
function useResize(
585
options?: UseResizeOptions
586
): SpringValues<{
587
width: number;
588
height: number;
589
}>;
590
591
interface UseResizeOptions extends Omit<SpringProps, 'to' | 'from'> {
592
/** Container element to observe (defaults to window) */
593
container?: MutableRefObject<HTMLElement | null | undefined>;
594
}
595
```
596
597
**Usage Examples:**
598
599
```typescript
600
import { useResize, animated } from "@react-spring/web";
601
602
// Window resize responsive
603
function ResponsiveBox() {
604
const { width, height } = useResize();
605
606
return (
607
<animated.div
608
style={{
609
width: width.to(w => w * 0.8),
610
height: height.to(h => h * 0.6)
611
}}
612
/>
613
);
614
}
615
616
// Element resize tracking
617
function ResizableContainer() {
618
const containerRef = useRef<HTMLDivElement>(null);
619
const { width } = useResize({ container: containerRef });
620
621
return (
622
<div ref={containerRef}>
623
<animated.div style={{ fontSize: width.to(w => w / 20) }}>
624
Scalable text
625
</animated.div>
626
</div>
627
);
628
}
629
```
630
631
### useInView
632
633
Creates animations triggered by element intersection with viewport.
634
635
```typescript { .api }
636
/**
637
* Creates intersection observer animations
638
* @param args - Intersection observer configuration
639
* @returns Tuple of element ref and boolean in-view state
640
*/
641
function useInView(args?: IntersectionArgs): [RefObject<any>, boolean];
642
643
/**
644
* Creates intersection observer animations with spring values
645
* @param props - Function returning spring configuration
646
* @param args - Intersection observer configuration
647
* @returns Tuple of element ref and spring values
648
*/
649
function useInView<Props extends object>(
650
props: () => Props & Valid<Props, UseSpringProps<Props>>,
651
args?: IntersectionArgs
652
): [RefObject<any>, SpringValues<PickAnimated<Props>>];
653
654
interface IntersectionArgs extends Omit<IntersectionObserverInit, 'root' | 'threshold'> {
655
/** Root element for intersection (defaults to viewport) */
656
root?: React.MutableRefObject<HTMLElement>;
657
/** Trigger animation only once */
658
once?: boolean;
659
/** Intersection amount trigger: 'any', 'all', number, or array */
660
amount?: 'any' | 'all' | number | number[];
661
}
662
```
663
664
**Usage Examples:**
665
666
```typescript
667
import { useInView, animated } from "@react-spring/web";
668
669
// Basic visibility detection
670
function FadeInOnScroll() {
671
const [ref, inView] = useInView();
672
673
return (
674
<div ref={ref}>
675
{inView ? 'Visible!' : 'Not visible'}
676
</div>
677
);
678
}
679
680
// Animated entrance on scroll
681
function AnimatedOnScroll() {
682
const [ref, springs] = useInView(
683
() => ({
684
from: { opacity: 0, y: 50 },
685
to: { opacity: 1, y: 0 },
686
}),
687
{ once: true }
688
);
689
690
return (
691
<animated.div ref={ref} style={springs}>
692
Fade in when scrolled into view
693
</animated.div>
694
);
695
}
696
697
// Custom intersection threshold
698
function PartiallyVisible() {
699
const [ref, springs] = useInView(
700
() => ({
701
from: { scale: 0.8 },
702
to: { scale: 1 },
703
}),
704
{ amount: 0.5 } // Trigger when 50% visible
705
);
706
707
return (
708
<animated.div ref={ref} style={springs}>
709
Scales when half visible
710
</animated.div>
711
);
712
}
713
```
714
715
## Common Spring Configuration
716
717
```typescript { .api }
718
interface SpringConfig {
719
/** Animation duration in milliseconds */
720
duration?: number;
721
/** Spring tension (stiffness) */
722
tension?: number;
723
/** Spring friction (damping) */
724
friction?: number;
725
/** Mass of the spring */
726
mass?: number;
727
/** Precision threshold for stopping */
728
precision?: number;
729
/** Velocity threshold for stopping */
730
velocity?: number;
731
/** Animation easing function */
732
easing?: EasingFunction;
733
/** Clamp values to prevent overshoot */
734
clamp?: boolean;
735
}
736
```