@@ -13,52 +13,48 @@ export const useSprings = (length, props) => {
13
13
const isFn = is . fun ( props )
14
14
15
15
// The controller maintains the animation values, starts and stops animations
16
- const [ controllers , ref ] = useMemo ( ( ) => {
17
- // Remove old controllers
18
- if ( ctrl . current ) {
19
- ctrl . current . map ( c => c . destroy ( ) )
20
- ctrl . current = undefined
21
- }
16
+ const [ controllers , setProps , ref , api ] = useMemo ( ( ) => {
22
17
let ref
23
18
return [
19
+ // Recreate the controllers whenever `length` changes
24
20
new Array ( length ) . fill ( ) . map ( ( _ , i ) => {
25
- const ctrl = new Ctrl ( )
26
- const newProps = isFn ? callProp ( props , i , ctrl ) : props [ i ]
21
+ const c = new Ctrl ( )
22
+ const newProps = isFn ? callProp ( props , i , c ) : props [ i ]
27
23
if ( i === 0 ) ref = newProps . ref
28
- return ctrl . update ( newProps )
24
+ return c . update ( newProps )
29
25
} ) ,
26
+ // This updates the controllers with new props
27
+ props =>
28
+ ctrl . current . forEach ( ( c , i ) => {
29
+ c . update ( is . fun ( props ) ? callProp ( props , i , c ) : props [ i ] )
30
+ if ( ! ref ) c . start ( )
31
+ } ) ,
32
+ // The imperative API is accessed via ref
30
33
ref ,
34
+ ref && {
35
+ start : ( ) =>
36
+ Promise . all ( ctrl . current . map ( c => new Promise ( r => c . start ( r ) ) ) ) ,
37
+ stop : finished => ctrl . current . forEach ( c => c . stop ( finished ) ) ,
38
+ get controllers ( ) {
39
+ return ctrl . current
40
+ } ,
41
+ } ,
31
42
]
32
43
} , [ length ] )
33
44
34
- ctrl . current = controllers
35
-
36
- // The hooks reference api gets defined here ...
37
- const api = useImperativeHandle ( ref , ( ) => ( {
38
- start : ( ) =>
39
- Promise . all ( ctrl . current . map ( c => new Promise ( r => c . start ( r ) ) ) ) ,
40
- stop : finished => ctrl . current . forEach ( c => c . stop ( finished ) ) ,
41
- get controllers ( ) {
42
- return ctrl . current
43
- } ,
44
- } ) )
45
-
46
- // This function updates the controllers
47
- const updateCtrl = useMemo (
48
- ( ) => updateProps =>
49
- ctrl . current . map ( ( c , i ) => {
50
- c . update ( isFn ? callProp ( updateProps , i , c ) : updateProps [ i ] )
51
- if ( ! ref ) c . start ( )
52
- } ) ,
53
- [ length ]
54
- )
45
+ // Attach the imperative API to its ref
46
+ useImperativeHandle ( ref , ( ) => api , [ api ] )
55
47
56
48
// Update controller if props aren't functional
57
49
useEffect ( ( ) => {
50
+ if ( ctrl . current !== controllers ) {
51
+ if ( ctrl . current ) ctrl . current . map ( c => c . destroy ( ) )
52
+ ctrl . current = controllers
53
+ }
58
54
if ( mounted . current ) {
59
- if ( ! isFn ) updateCtrl ( props )
55
+ if ( ! isFn ) setProps ( props )
60
56
} else if ( ! ref ) {
61
- ctrl . current . forEach ( c => c . start ( ) )
57
+ controllers . forEach ( c => c . start ( ) )
62
58
}
63
59
} )
64
60
@@ -69,12 +65,12 @@ export const useSprings = (length, props) => {
69
65
} , [ ] )
70
66
71
67
// Return animated props, or, anim-props + the update-setter above
72
- const propValues = ctrl . current . map ( c => c . getValues ( ) )
68
+ const values = ctrl . current . map ( c => c . getValues ( ) )
73
69
return isFn
74
70
? [
75
- propValues ,
76
- updateCtrl ,
71
+ values ,
72
+ setProps ,
77
73
finished => ctrl . current . forEach ( c => c . stop ( finished ) ) ,
78
74
]
79
- : propValues
75
+ : values
80
76
}
0 commit comments