11import React , {
22 Fragment ,
33 createContext ,
4- useCallback ,
54 useContext ,
65 useEffect ,
76 useMemo ,
@@ -32,6 +31,7 @@ import { Reason, transition } from './utils/transition'
3231import { OpenClosedProvider , State , useOpenClosed } from '../../internal/open-closed'
3332import { useServerHandoffComplete } from '../../hooks/use-server-handoff-complete'
3433import { useSyncRefs } from '../../hooks/use-sync-refs'
34+ import { useLatestValue } from '../../hooks/use-latest-value'
3535
3636type ID = ReturnType < typeof useId >
3737
@@ -103,8 +103,8 @@ function useParentNesting() {
103103
104104interface NestingContextValues {
105105 children : MutableRefObject < { id : ID ; state : TreeStates } [ ] >
106- register : ( id : ID ) => ( ) => void
107- unregister : ( id : ID , strategy ?: RenderStrategy ) => void
106+ register : MutableRefObject < ( id : ID ) => ( ) => void >
107+ unregister : MutableRefObject < ( id : ID , strategy ?: RenderStrategy ) => void >
108108}
109109
110110let NestingContext = createContext < NestingContextValues | null > ( null )
@@ -118,48 +118,38 @@ function hasChildren(
118118}
119119
120120function useNesting ( done ?: ( ) => void ) {
121- let doneRef = useRef ( done )
121+ let doneRef = useLatestValue ( done )
122122 let transitionableChildren = useRef < NestingContextValues [ 'children' ] [ 'current' ] > ( [ ] )
123123 let mounted = useIsMounted ( )
124124
125- useEffect ( ( ) => {
126- doneRef . current = done
127- } , [ done ] )
128-
129- let unregister = useCallback (
130- ( childId : ID , strategy = RenderStrategy . Hidden ) => {
131- let idx = transitionableChildren . current . findIndex ( ( { id } ) => id === childId )
132- if ( idx === - 1 ) return
133-
134- match ( strategy , {
135- [ RenderStrategy . Unmount ] ( ) {
136- transitionableChildren . current . splice ( idx , 1 )
137- } ,
138- [ RenderStrategy . Hidden ] ( ) {
139- transitionableChildren . current [ idx ] . state = TreeStates . Hidden
140- } ,
141- } )
142-
143- if ( ! hasChildren ( transitionableChildren ) && mounted . current ) {
144- doneRef . current ?.( )
145- }
146- } ,
147- [ doneRef , mounted , transitionableChildren ]
148- )
125+ let unregister = useLatestValue ( ( childId : ID , strategy = RenderStrategy . Hidden ) => {
126+ let idx = transitionableChildren . current . findIndex ( ( { id } ) => id === childId )
127+ if ( idx === - 1 ) return
128+
129+ match ( strategy , {
130+ [ RenderStrategy . Unmount ] ( ) {
131+ transitionableChildren . current . splice ( idx , 1 )
132+ } ,
133+ [ RenderStrategy . Hidden ] ( ) {
134+ transitionableChildren . current [ idx ] . state = TreeStates . Hidden
135+ } ,
136+ } )
149137
150- let register = useCallback (
151- ( childId : ID ) => {
152- let child = transitionableChildren . current . find ( ( { id } ) => id === childId )
153- if ( ! child ) {
154- transitionableChildren . current . push ( { id : childId , state : TreeStates . Visible } )
155- } else if ( child . state !== TreeStates . Visible ) {
156- child . state = TreeStates . Visible
157- }
158-
159- return ( ) => unregister ( childId , RenderStrategy . Unmount )
160- } ,
161- [ transitionableChildren , unregister ]
162- )
138+ if ( ! hasChildren ( transitionableChildren ) && mounted . current ) {
139+ doneRef . current ?.( )
140+ }
141+ } )
142+
143+ let register = useLatestValue ( ( childId : ID ) => {
144+ let child = transitionableChildren . current . find ( ( { id } ) => id === childId )
145+ if ( ! child ) {
146+ transitionableChildren . current . push ( { id : childId , state : TreeStates . Visible } )
147+ } else if ( child . state !== TreeStates . Visible ) {
148+ child . state = TreeStates . Visible
149+ }
150+
151+ return ( ) => unregister . current ( childId , RenderStrategy . Unmount )
152+ } )
163153
164154 return useMemo (
165155 ( ) => ( {
@@ -226,6 +216,7 @@ let TransitionChild = forwardRefWithAs(function TransitionChild<
226216
227217 let { show, appear, initial } = useTransitionContext ( )
228218 let { register, unregister } = useParentNesting ( )
219+ let prevShow = useRef ( undefined )
229220
230221 let id = useId ( )
231222
@@ -236,14 +227,14 @@ let TransitionChild = forwardRefWithAs(function TransitionChild<
236227 // transitioning ourselves. Otherwise we would unmount before the transitions are finished.
237228 if ( ! isTransitioning . current ) {
238229 setState ( TreeStates . Hidden )
239- unregister ( id )
230+ unregister . current ( id )
240231 events . current . afterLeave ( )
241232 }
242233 } )
243234
244235 useIsoMorphicEffect ( ( ) => {
245236 if ( ! id ) return
246- return register ( id )
237+ return register . current ( id )
247238 } , [ register , id ] )
248239
249240 useIsoMorphicEffect ( ( ) => {
@@ -258,8 +249,8 @@ let TransitionChild = forwardRefWithAs(function TransitionChild<
258249 }
259250
260251 match ( state , {
261- [ TreeStates . Hidden ] : ( ) => unregister ( id ) ,
262- [ TreeStates . Visible ] : ( ) => register ( id ) ,
252+ [ TreeStates . Hidden ] : ( ) => unregister . current ( id ) ,
253+ [ TreeStates . Visible ] : ( ) => register . current ( id ) ,
263254 } )
264255 } , [ state , id , register , unregister , show , strategy ] )
265256
@@ -290,6 +281,7 @@ let TransitionChild = forwardRefWithAs(function TransitionChild<
290281 let node = container . current
291282 if ( ! node ) return
292283 if ( skip ) return
284+ if ( show === prevShow . current ) return
293285
294286 isTransitioning . current = true
295287
@@ -323,7 +315,7 @@ let TransitionChild = forwardRefWithAs(function TransitionChild<
323315 // ourselves.
324316 if ( ! hasChildren ( nesting ) ) {
325317 setState ( TreeStates . Hidden )
326- unregister ( id )
318+ unregister . current ( id )
327319 events . current . afterLeave ( )
328320 }
329321 }
@@ -345,6 +337,10 @@ let TransitionChild = forwardRefWithAs(function TransitionChild<
345337 leaveToClasses ,
346338 ] )
347339
340+ useIsoMorphicEffect ( ( ) => {
341+ prevShow . current = show
342+ } , [ show ] )
343+
348344 let propsWeControl = { ref : transitionRef }
349345 let passthroughProps = rest
350346
0 commit comments