11import React from 'react' ;
2- import type { TriggerProps } from '..' ;
32import { useEvent } from '@rc-component/util' ;
43import type { UniqueShowOptions } from '../context' ;
54
@@ -10,24 +9,61 @@ import type { UniqueShowOptions } from '../context';
109 * 3. When `target` change to another one:
1110 * a. We wait motion finish of previous popup.
1211 * b. Then we set new target and show the popup.
12+ * 4. During appear/enter animation, cache new options and apply after animation completes.
1313 */
1414export default function useTargetState ( ) : [
1515 trigger : ( options : UniqueShowOptions | false ) => void ,
1616 open : boolean ,
1717 /* Will always cache last which is not null */
1818 cacheOptions : UniqueShowOptions | null ,
19+ onVisibleChanged : ( visible : boolean ) => void ,
1920] {
2021 const [ options , setOptions ] = React . useState < UniqueShowOptions | null > ( null ) ;
2122 const [ open , setOpen ] = React . useState ( false ) ;
23+ const [ isAnimating , setIsAnimating ] = React . useState ( false ) ;
24+ const pendingOptionsRef = React . useRef < UniqueShowOptions | null > ( null ) ;
2225
2326 const trigger = useEvent ( ( nextOptions : UniqueShowOptions | false ) => {
2427 if ( nextOptions === false ) {
28+ // 隐藏时清除待处理的选项
29+ pendingOptionsRef . current = null ;
2530 setOpen ( false ) ;
2631 } else {
27- setOpen ( true ) ;
28- setOptions ( nextOptions ) ;
32+ if ( isAnimating && open ) {
33+ // 如果正在动画中(appear 或 enter),缓存新的 options
34+ pendingOptionsRef . current = nextOptions ;
35+ } else {
36+ // 没有动画或者是首次显示,直接应用
37+ setOpen ( true ) ;
38+ setOptions ( nextOptions ) ;
39+ pendingOptionsRef . current = null ;
40+ }
2941 }
3042 } ) ;
3143
32- return [ trigger , open , options ] ;
44+ const onVisibleChanged = useEvent ( ( visible : boolean ) => {
45+ if ( visible ) {
46+ // 动画进入完成,检查是否有待处理的选项
47+ setIsAnimating ( false ) ;
48+ if ( pendingOptionsRef . current ) {
49+ const pendingOptions = pendingOptionsRef . current ;
50+ pendingOptionsRef . current = null ;
51+ // 应用待处理的选项
52+ setOptions ( pendingOptions ) ;
53+ }
54+ } else {
55+ // 动画离开完成
56+ setIsAnimating ( false ) ;
57+ pendingOptionsRef . current = null ;
58+ }
59+ } ) ;
60+
61+ // 当开始显示时标记为动画中
62+ React . useEffect ( ( ) => {
63+ if ( open && options ) {
64+ setIsAnimating ( true ) ;
65+ }
66+ } , [ open , options ] ) ;
67+
68+ return [ trigger , open , options , onVisibleChanged ] ;
3369}
0 commit comments