@@ -20,12 +20,15 @@ export function useTransition<T>(
2020 props : any ,
2121 deps ?: any
2222) {
23- const { ref, reset, trail = 0 , expires = Infinity } = props
23+ const { key , ref, reset, trail = 0 , expires = Infinity } = props
2424
2525 // Every item has its own transition.
2626 const items = toArray ( data )
2727 const transitions : Transition [ ] = [ ]
2828
29+ // Explicit keys are used to associate transitions with immutable items.
30+ const keys = is . und ( key ) ? key : is . fun ( key ) ? items . map ( key ) : toArray ( key )
31+
2932 // The "onRest" callbacks need a ref to the latest transitions.
3033 const usedTransitions = useRef < Transition [ ] | null > ( null )
3134 const prevTransitions = usedTransitions . current
@@ -38,25 +41,25 @@ export function useTransition<T>(
3841 usedTransitions . current ! . forEach ( t => t . spring . destroy ( ) )
3942 } )
4043
41- // Determine which items are new.
42- let newItems = items
43- if ( prevTransitions && ! reset ) {
44- // Reuse old transitions unless expired.
44+ // Determine which transitions can be reused.
45+ const prevKeys : any [ ] = [ ]
46+ if ( prevTransitions && ! reset )
4547 prevTransitions . forEach ( t => {
4648 if ( is . und ( t . expiresBy ) ) {
49+ prevKeys . push ( keys ? t . key : t . item )
4750 transitions . push ( t )
4851 } else {
4952 clearTimeout ( t . expirationId )
5053 }
5154 } )
52- const oldItems = transitions . map ( t => t . item )
53- newItems = newItems . filter ( item => oldItems . indexOf ( item ) < 0 )
54- }
5555
5656 // Append new transitions for new items.
57- newItems . forEach ( item => {
58- const spring = new Controller ( )
59- transitions . push ( { id : spring . id , item, phase : Phase . Mount , spring } )
57+ items . forEach ( ( item , i ) => {
58+ const key = keys && keys [ i ]
59+ if ( prevKeys . indexOf ( keys ? key : item ) < 0 ) {
60+ const spring = new Controller ( )
61+ transitions . push ( { id : spring . id , key, item, phase : MOUNT , spring } )
62+ }
6063 } )
6164
6265 // Track cumulative delay for the "trail" prop.
@@ -81,7 +84,7 @@ export function useTransition<T>(
8184 from = props . from
8285 }
8386 } else {
84- const isDeleted = items . indexOf ( t . item ) < 0
87+ const isDeleted = ( keys || items ) . indexOf ( keys ? t . key : t . item ) < 0
8588 if ( t . phase < LEAVE ) {
8689 if ( isDeleted ) {
8790 to = props . leave
@@ -185,6 +188,7 @@ interface Change {
185188
186189interface Transition < T = any > {
187190 id : number
191+ key ?: keyof any
188192 item : T
189193 phase : Phase
190194 spring : Controller
0 commit comments