11import { useEvent } from 'rc-util' ;
22import useState from 'rc-util/lib/hooks/useState' ;
3+ import useSyncState from 'rc-util/lib/hooks/useSyncState' ;
34import * as React from 'react' ;
45import { useEffect , useRef } from 'react' ;
56import type { CSSMotionProps } from '../CSSMotion' ;
@@ -51,9 +52,11 @@ export default function useStatus(
5152) : [ MotionStatus , StepStatus , React . CSSProperties , boolean ] {
5253 // Used for outer render usage to avoid `visible: false & status: none` to render nothing
5354 const [ asyncVisible , setAsyncVisible ] = useState < boolean > ( ) ;
54- const [ status , setStatus ] = useState < MotionStatus > ( STATUS_NONE ) ;
55+ const [ getStatus , setStatus ] = useSyncState < MotionStatus > ( STATUS_NONE ) ;
5556 const [ style , setStyle ] = useState < React . CSSProperties | undefined > ( null ) ;
5657
58+ const currentStatus = getStatus ( ) ;
59+
5760 const mountedRef = useRef ( false ) ;
5861 const deadlineRef = useRef ( null ) ;
5962
@@ -69,11 +72,12 @@ export default function useStatus(
6972 * Clean up status & style
7073 */
7174 function updateMotionEndStatus ( ) {
72- setStatus ( STATUS_NONE , true ) ;
75+ setStatus ( STATUS_NONE ) ;
7376 setStyle ( null , true ) ;
7477 }
7578
7679 const onInternalMotionEnd = useEvent ( ( event : MotionEvent ) => {
80+ const status = getStatus ( ) ;
7781 // Do nothing since not in any transition status.
7882 // This may happen when `motionDeadline` trigger.
7983 if ( status === STATUS_NONE ) {
@@ -140,44 +144,48 @@ export default function useStatus(
140144 [ STEP_PREPARE ] ?: MotionPrepareEventHandler ;
141145 [ STEP_START ] ?: MotionEventHandler ;
142146 [ STEP_ACTIVE ] ?: MotionEventHandler ;
143- } > ( ( ) => getEventHandlers ( status ) , [ status ] ) ;
144-
145- const [ startStep , step ] = useStepQueue ( status , ! supportMotion , newStep => {
146- // Only prepare step can be skip
147- if ( newStep === STEP_PREPARE ) {
148- const onPrepare = eventHandlers [ STEP_PREPARE ] ;
149- if ( ! onPrepare ) {
150- return SkipStep ;
147+ } > ( ( ) => getEventHandlers ( currentStatus ) , [ currentStatus ] ) ;
148+
149+ const [ startStep , step ] = useStepQueue (
150+ currentStatus ,
151+ ! supportMotion ,
152+ newStep => {
153+ // Only prepare step can be skip
154+ if ( newStep === STEP_PREPARE ) {
155+ const onPrepare = eventHandlers [ STEP_PREPARE ] ;
156+ if ( ! onPrepare ) {
157+ return SkipStep ;
158+ }
159+
160+ return onPrepare ( getDomElement ( ) ) ;
151161 }
152162
153- return onPrepare ( getDomElement ( ) ) ;
154- }
155-
156- // Rest step is sync update
157- if ( step in eventHandlers ) {
158- setStyle ( eventHandlers [ step ] ?.( getDomElement ( ) , null ) || null ) ;
159- }
163+ // Rest step is sync update
164+ if ( step in eventHandlers ) {
165+ setStyle ( eventHandlers [ step ] ?.( getDomElement ( ) , null ) || null ) ;
166+ }
160167
161- if ( step === STEP_ACTIVE && status !== STATUS_NONE ) {
162- // Patch events when motion needed
163- patchMotionEvents ( getDomElement ( ) ) ;
164-
165- if ( motionDeadline > 0 ) {
166- clearTimeout ( deadlineRef . current ) ;
167- deadlineRef . current = setTimeout ( ( ) => {
168- onInternalMotionEnd ( {
169- deadline : true ,
170- } as MotionEvent ) ;
171- } , motionDeadline ) ;
168+ if ( step === STEP_ACTIVE && currentStatus !== STATUS_NONE ) {
169+ // Patch events when motion needed
170+ patchMotionEvents ( getDomElement ( ) ) ;
171+
172+ if ( motionDeadline > 0 ) {
173+ clearTimeout ( deadlineRef . current ) ;
174+ deadlineRef . current = setTimeout ( ( ) => {
175+ onInternalMotionEnd ( {
176+ deadline : true ,
177+ } as MotionEvent ) ;
178+ } , motionDeadline ) ;
179+ }
172180 }
173- }
174181
175- if ( step === STEP_PREPARED ) {
176- updateMotionEndStatus ( ) ;
177- }
182+ if ( step === STEP_PREPARED ) {
183+ updateMotionEndStatus ( ) ;
184+ }
178185
179- return DoStep ;
180- } ) ;
186+ return DoStep ;
187+ } ,
188+ ) ;
181189
182190 const active = isActive ( step ) ;
183191 activeRef . current = active ;
@@ -231,11 +239,11 @@ export default function useStatus(
231239 useEffect ( ( ) => {
232240 if (
233241 // Cancel appear
234- ( status === STATUS_APPEAR && ! motionAppear ) ||
242+ ( currentStatus === STATUS_APPEAR && ! motionAppear ) ||
235243 // Cancel enter
236- ( status === STATUS_ENTER && ! motionEnter ) ||
244+ ( currentStatus === STATUS_ENTER && ! motionEnter ) ||
237245 // Cancel leave
238- ( status === STATUS_LEAVE && ! motionLeave )
246+ ( currentStatus === STATUS_LEAVE && ! motionLeave )
239247 ) {
240248 setStatus ( STATUS_NONE ) ;
241249 }
@@ -257,14 +265,14 @@ export default function useStatus(
257265 firstMountChangeRef . current = true ;
258266 }
259267
260- if ( asyncVisible !== undefined && status === STATUS_NONE ) {
268+ if ( asyncVisible !== undefined && currentStatus === STATUS_NONE ) {
261269 // Skip first render is invisible since it's nothing changed
262270 if ( firstMountChangeRef . current || asyncVisible ) {
263271 onVisibleChanged ?.( asyncVisible ) ;
264272 }
265273 firstMountChangeRef . current = true ;
266274 }
267- } , [ asyncVisible , status ] ) ;
275+ } , [ asyncVisible , currentStatus ] ) ;
268276
269277 // ============================ Styles ============================
270278 let mergedStyle = style ;
@@ -275,5 +283,5 @@ export default function useStatus(
275283 } ;
276284 }
277285
278- return [ status , step , mergedStyle , asyncVisible ?? visible ] ;
286+ return [ currentStatus , step , mergedStyle , asyncVisible ?? visible ] ;
279287}
0 commit comments