Skip to content

Commit e22d996

Browse files
committed
test(fab): add test cases of fab
1 parent 6f30c4f commit e22d996

File tree

6 files changed

+288
-62
lines changed

6 files changed

+288
-62
lines changed

site/test-coverage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module.exports = {
1919
drawer: { statements: '98.63%', branches: '100%', functions: '96.42%', lines: '100%' },
2020
dropdownMenu: { statements: '92.94%', branches: '82.81%', functions: '100%', lines: '92.5%' },
2121
empty: { statements: '100%', branches: '100%', functions: '100%', lines: '100%' },
22-
fab: { statements: '5.4%', branches: '0%', functions: '0%', lines: '5.4%' },
22+
fab: { statements: '100%', branches: '100%', functions: '100%', lines: '100%' },
2323
footer: { statements: '100%', branches: '100%', functions: '100%', lines: '100%' },
2424
form: { statements: '2.79%', branches: '0%', functions: '0%', lines: '2.95%' },
2525
grid: { statements: '100%', branches: '100%', functions: '100%', lines: '100%' },

src/fab/Fab.tsx

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)