1- import React , { forwardRef , useImperativeHandle , useRef , useMemo , useState } from 'react' ;
1+ import React , { forwardRef , useImperativeHandle , useRef , useMemo , useState , useEffect } from 'react' ;
22import { isArray , isBoolean } from 'lodash-es' ;
33import classNames from 'classnames' ;
44import { useClickAway } from 'ahooks' ;
@@ -31,6 +31,7 @@ export const syncOpenedState = (
3131 getOpenedSide : ( opened : SwipeCellProps [ 'opened' ] ) => SideType | undefined ,
3232 expand : ( side : SideType ) => void ,
3333 close : ( ) => void ,
34+ setTimer : ( callback : ( ) => void , delay : number ) => void ,
3435) => {
3536 if ( ! rootRef . current ) return ;
3637
@@ -39,7 +40,7 @@ export const syncOpenedState = (
3940 if ( side === 'left' || side === 'right' ) {
4041 // 初始化 expanded,等待 dom 加载完,获取 left/right 宽度后无动画设置展开状态
4142 // 防止 left/right 为列表时,获取真实宽度有误
42- setTimeout ( ( ) => {
43+ setTimer ( ( ) => {
4344 expand ( side ) ;
4445 } , 100 ) ;
4546 } else {
@@ -54,12 +55,36 @@ const SwipeCell = forwardRef<SwipeCellRef, SwipeCellProps>((originProps, ref) =>
5455 const rootRef = useRef < HTMLDivElement > ( null ) ;
5556 const leftRef = useRef < HTMLDivElement > ( null ) ;
5657 const rightRef = useRef < HTMLDivElement > ( null ) ;
58+ const timersRef = useRef < ReturnType < typeof setTimeout > [ ] > ( [ ] ) ;
5759 const [ curSure , setSure ] = useState < {
5860 content : Sure ;
5961 width : number ;
6062 transform : string ;
6163 } > ( { content : '' , width : 0 , transform : 'none' } ) ;
6264
65+ // Helper function to set timers that are tracked for cleanup
66+ const setTimer = ( callback : ( ) => void , delay : number ) => {
67+ const timerId = setTimeout ( ( ) => {
68+ // Remove completed timer from tracking array
69+ const index = timersRef . current . indexOf ( timerId ) ;
70+ if ( index > - 1 ) {
71+ timersRef . current . splice ( index , 1 ) ;
72+ }
73+ callback ( ) ;
74+ } , delay ) ;
75+ timersRef . current . push ( timerId ) ;
76+ return timerId ;
77+ } ;
78+
79+ // Cleanup all timers on unmount
80+ useEffect (
81+ ( ) => ( ) => {
82+ timersRef . current . forEach ( ( timerId ) => clearTimeout ( timerId ) ) ;
83+ timersRef . current = [ ] ;
84+ } ,
85+ [ ] ,
86+ ) ;
87+
6388 const getOpenedSide = ( opened ) => {
6489 if ( isBoolean ( opened ) ) {
6590 if ( rightRef . current ) {
@@ -108,7 +133,7 @@ const SwipeCell = forwardRef<SwipeCellRef, SwipeCellProps>((originProps, ref) =>
108133 setX ( 0 ) ;
109134 onChange ( ) ;
110135 if ( curSure . content ) {
111- setTimeout ( ( ) => {
136+ setTimer ( ( ) => {
112137 setSure ( {
113138 content : '' ,
114139 width : 0 ,
@@ -152,9 +177,9 @@ const SwipeCell = forwardRef<SwipeCellRef, SwipeCellProps>((originProps, ref) =>
152177 } else {
153178 close ( ) ;
154179 }
155- setTimeout ( ( ) => {
180+ setTimer ( ( ) => {
156181 ctx . dragging = false ;
157- } ) ;
182+ } , 0 ) ;
158183 } else {
159184 setX ( offsetX ) ;
160185 }
@@ -178,7 +203,7 @@ const SwipeCell = forwardRef<SwipeCellRef, SwipeCellProps>((originProps, ref) =>
178203 } ) ) ;
179204
180205 useLayoutEffect ( ( ) => {
181- syncOpenedState ( rootRef , opened , getOpenedSide , expand , close ) ;
206+ syncOpenedState ( rootRef , opened , getOpenedSide , expand , close , setTimer ) ;
182207 // 可以保证expand,close正常执行
183208 // eslint-disable-next-line react-hooks/exhaustive-deps
184209 } , [ opened , rootRef . current ] ) ;
@@ -200,12 +225,12 @@ const SwipeCell = forwardRef<SwipeCellRef, SwipeCellProps>((originProps, ref) =>
200225 width : getSideOffsetX ( side ) ,
201226 transform : side === 'left' ? 'translateX(-100%)' : 'translateX(100%)' ,
202227 } ) ;
203- setTimeout ( ( ) => {
228+ setTimer ( ( ) => {
204229 setSure ( ( current ) => ( {
205230 ...current ,
206231 transform : 'none' ,
207232 } ) ) ;
208- } ) ;
233+ } , 0 ) ;
209234 return ;
210235 }
211236
0 commit comments