@@ -102,9 +102,23 @@ const PopupInner = React.forwardRef<PopupInnerRef, PopupInnerProps>(
102102 const [ status , goNextStatus ] = useVisibleStatus ( visible , doMeasure ) ;
103103
104104 // ======================== Aligns ========================
105- const [ alignInfo , setAlignInfo ] = useState < AlignType > ( null ) ;
105+ /**
106+ * `alignedClassName` may modify `source` size,
107+ * which means one time align may not move to the correct position at once.
108+ *
109+ * We will reset `alignTimes` for each status switch to `alignPre`
110+ * and let `rc-align` to align for multiple times to ensure get final stable place.
111+ * Currently we mark `alignTimes < 2` repeat align, it will increase if user report for align issue.
112+ */
113+ const [ alignTimes , setAlignTimes ] = useState ( 0 ) ;
106114 const prepareResolveRef = useRef < ( value ?: unknown ) => void > ( ) ;
107115
116+ useLayoutEffect ( ( ) => {
117+ if ( status === 'alignPre' ) {
118+ setAlignTimes ( 0 ) ;
119+ }
120+ } , [ status ] ) ;
121+
108122 // `target` on `rc-align` can accept as a function to get the bind element or a point.
109123 // ref: https://www.npmjs.com/package/rc-align
110124 function getAlignTarget ( ) {
@@ -120,11 +134,13 @@ const PopupInner = React.forwardRef<PopupInnerRef, PopupInnerProps>(
120134
121135 function onInternalAlign ( popupDomNode : HTMLElement , matchAlign : AlignType ) {
122136 const nextAlignedClassName = getClassNameFromAlign ( matchAlign ) ;
137+
123138 if ( alignedClassName !== nextAlignedClassName ) {
124139 setAlignedClassName ( nextAlignedClassName ) ;
125140 }
126141
127- setAlignInfo ( matchAlign ) ;
142+ // We will retry multi times to make sure that the element has been align in the right position.
143+ setAlignTimes ( ( val ) => val + 1 ) ;
128144
129145 if ( status === 'align' ) {
130146 onAlign ?.( popupDomNode , matchAlign ) ;
@@ -133,19 +149,17 @@ const PopupInner = React.forwardRef<PopupInnerRef, PopupInnerProps>(
133149
134150 // Delay to go to next status
135151 useLayoutEffect ( ( ) => {
136- if ( alignInfo && status === 'align' ) {
137- const nextAlignedClassName = getClassNameFromAlign ( alignInfo ) ;
138-
152+ if ( status === 'align' ) {
139153 // Repeat until not more align needed
140- if ( alignedClassName !== nextAlignedClassName ) {
154+ if ( alignTimes < 2 ) {
141155 forceAlign ( ) ;
142156 } else {
143157 goNextStatus ( function ( ) {
144158 prepareResolveRef . current ?.( ) ;
145159 } ) ;
146160 }
147161 }
148- } , [ alignInfo ] ) ;
162+ } , [ alignTimes ] ) ;
149163
150164 // ======================== Motion ========================
151165 const motion = { ...getMotion ( props ) } ;
0 commit comments