@@ -41,31 +41,27 @@ const Fab: React.FC<FabProps> = (originProps) => {
4141 x : 16 ,
4242 y : 32 ,
4343 } ) ;
44- let switchPos = {
44+ const switchPosRef = useRef ( {
4545 hasMoved : false , // exclude click event
4646 x : btnSwitchPos . x , // right
4747 y : btnSwitchPos . y , // bottom
4848 startX : 0 ,
4949 startY : 0 ,
5050 endX : 0 ,
5151 endY : 0 ,
52- } ;
52+ } ) ;
5353
5454 const onClickHandle = ( e : React . MouseEvent < HTMLDivElement > ) => {
5555 onClick ( { e } ) ;
5656 } ;
5757
58- const fabStyle = {
59- ...props . style ,
60- right : `${ btnSwitchPos . x } px` ,
61- bottom : `${ btnSwitchPos . y } px` ,
62- } ;
63-
6458 const onTouchStart = ( e : React . TouchEvent < HTMLDivElement > ) => {
6559 props . onDragStart ?.( { e } ) ;
6660
67- switchPos = {
68- ...switchPos ,
61+ switchPosRef . current = {
62+ ...switchPosRef . current ,
63+ x : btnSwitchPos . x ,
64+ y : btnSwitchPos . y ,
6965 startX : e . touches [ 0 ] . clientX ,
7066 startY : e . touches [ 0 ] . clientY ,
7167 } ;
@@ -88,14 +84,6 @@ const Fab: React.FC<FabProps> = (originProps) => {
8884 } ;
8985
9086 const onTouchMove = ( e : TouchEvent ) => {
91- if ( ! switchPos . hasMoved ) {
92- switchPos = {
93- ...switchPos ,
94- startX : e . touches [ 0 ] . clientX ,
95- startY : e . touches [ 0 ] . clientY ,
96- } ;
97- }
98-
9987 e . stopPropagation ( ) ;
10088 e . preventDefault ( ) ;
10189
@@ -107,15 +95,15 @@ const Fab: React.FC<FabProps> = (originProps) => {
10795 return ;
10896 }
10997
110- const offsetX = e . touches [ 0 ] . clientX - switchPos . startX ;
111- const offsetY = e . touches [ 0 ] . clientY - switchPos . startY ;
112- const x = Math . floor ( switchPos . x - offsetX ) ;
113- const y = Math . floor ( switchPos . y - offsetY ) ;
98+ const offsetX = e . touches [ 0 ] . clientX - switchPosRef . current . startX ;
99+ const offsetY = e . touches [ 0 ] . clientY - switchPosRef . current . startY ;
100+ const x = Math . floor ( switchPosRef . current . x - offsetX ) ;
101+ const y = Math . floor ( switchPosRef . current . y - offsetY ) ;
114102
115103 const [ newX , newY ] = getSwitchButtonSafeAreaXY ( x , y ) ;
116104
117105 const toChangeData = { ...btnSwitchPos } ;
118- const toChangePos = { ...switchPos , hasMoved : true } ;
106+ const toChangePos = { ...switchPosRef . current , hasMoved : true } ;
119107
120108 if ( props . draggable !== 'vertical' ) {
121109 toChangeData . x = newX ;
@@ -125,50 +113,53 @@ const Fab: React.FC<FabProps> = (originProps) => {
125113 toChangeData . y = newY ;
126114 toChangePos . endY = newY ;
127115 }
128- switchPos = toChangePos ;
116+ switchPosRef . current = toChangePos ;
129117 setBtnSwitchPos ( toChangeData ) ;
130118 } ;
131119
132120 useEffect ( ( ) => {
133121 const fab = fabRef . current ;
134122 fab ?. addEventListener ( 'touchmove' , onTouchMove , { passive : false } ) ;
123+
124+ return ( ) => {
125+ fab ?. removeEventListener ( 'touchmove' , onTouchMove ) ;
126+ } ;
135127 // eslint-disable-next-line react-hooks/exhaustive-deps
136- } , [ ] ) ;
128+ } , [ props . draggable , fabButtonSize . width , fabButtonSize . height ] ) ;
137129
138130 const setSwitchPosition = ( switchX : number , switchY : number ) => {
139131 const [ newSwitchX , newSwitchY ] = getSwitchButtonSafeAreaXY ( switchX , switchY ) ;
140- switchPos = {
141- ...switchPos ,
132+ switchPosRef . current = {
133+ ...switchPosRef . current ,
142134 x : newSwitchX ,
143135 y : newSwitchY ,
144136 } ;
145137
146- if ( props . draggable !== 'vertical' ) {
147- setBtnSwitchPos ( {
148- ...btnSwitchPos ,
149- x : switchX ,
150- } ) ;
151- }
152- if ( props . draggable !== 'horizontal' ) {
153- setBtnSwitchPos ( {
154- ...btnSwitchPos ,
155- y : switchY ,
156- } ) ;
157- }
138+ // 使用函数式更新避免闭包陷阱
139+ setBtnSwitchPos ( ( prev ) => {
140+ const newPos = { ...prev } ;
141+ if ( props . draggable !== 'vertical' ) {
142+ newPos . x = newSwitchX ;
143+ }
144+ if ( props . draggable !== 'horizontal' ) {
145+ newPos . y = newSwitchY ;
146+ }
147+ return newPos ;
148+ } ) ;
158149 } ;
159150
160151 const onTouchEnd = ( e : React . TouchEvent < HTMLDivElement > ) => {
161- if ( ! switchPos . hasMoved ) {
152+ if ( ! switchPosRef . current . hasMoved ) {
162153 return ;
163154 }
164155 props . onDragEnd ?.( { e } ) ;
165- switchPos = {
166- ...switchPos ,
156+ switchPosRef . current = {
157+ ...switchPosRef . current ,
167158 startX : 0 ,
168159 startY : 0 ,
169160 hasMoved : false ,
170161 } ;
171- setSwitchPosition ( switchPos . endX , switchPos . endY ) ;
162+ setSwitchPosition ( switchPosRef . current . endX , switchPosRef . current . endY ) ;
172163 } ;
173164 const defaultContent = (
174165 < Button
@@ -183,11 +174,21 @@ const Fab: React.FC<FabProps> = (originProps) => {
183174 </ Button >
184175 ) ;
185176
177+ const fabStyle = props . draggable
178+ ? {
179+ right : `${ btnSwitchPos . x } px` ,
180+ bottom : `${ btnSwitchPos . y } px` ,
181+ }
182+ : props . style || {
183+ right : `${ btnSwitchPos . x } px` ,
184+ bottom : `${ btnSwitchPos . y } px` ,
185+ } ;
186+
186187 return (
187188 < div
188189 ref = { fabRef }
189190 className = { fabClass }
190- style = { props . draggable && fabButtonSize . width ? { ... fabStyle } : props . style }
191+ style = { fabStyle }
191192 onClick = { onClickHandle }
192193 onTouchStart = { onTouchStart }
193194 onTouchEnd = { onTouchEnd }
0 commit comments