Skip to content

Commit dd5218b

Browse files
committed
chore: Use batch to update state
1 parent f7bc8ac commit dd5218b

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

src/Overflow.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ function Overflow<ItemType = any>(
6565
function registerSize(key: React.Key, width: number) {
6666
setItemWidths((origin) => {
6767
const clone = new Map(origin);
68-
console.log('==>>>', key, width);
6968

7069
if (!width) {
7170
clone.delete(key);
@@ -77,12 +76,9 @@ function Overflow<ItemType = any>(
7776
}
7877

7978
function registerOverflowSize(_: React.Key, width: number) {
80-
console.log('Overflow >>>', width);
8179
setOverflowWidth(width);
8280
}
8381

84-
console.log('BATCH >>>', containerWidth, overflowWidth, itemWidths);
85-
8682
// ================================ Render ================================
8783
let overflowNode = (
8884
<div className={classNames(prefixCls, className)} style={style} ref={ref}>

src/hooks/useBatchState.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useRef, useState } from 'react';
2+
import { beforeFrame, cancelBeforeFrame } from '../util';
23

34
/**
45
* State generate. Return a `setState` but it will flush all state with one render to save perf.
@@ -7,6 +8,7 @@ export function useBatchState() {
78
const [, forceUpdate] = useState({});
89
const statesRef = useRef<any[]>([]);
910
let walkingIndex = 0;
11+
let beforeFrameId: number = 0;
1012

1113
function createState<T>(
1214
defaultValue: T,
@@ -25,7 +27,12 @@ export function useBatchState() {
2527
function setValue(val: any) {
2628
statesRef.current[myIndex] = typeof val === 'function' ? val(value) : val;
2729

28-
forceUpdate({});
30+
cancelBeforeFrame(beforeFrameId);
31+
32+
// Flush with batch
33+
beforeFrameId = beforeFrame(() => {
34+
forceUpdate({});
35+
});
2936
}
3037

3138
return [value, setValue];

src/util.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,29 @@ export function getFullWidth(element: HTMLElement) {
1212
}
1313

1414
// =================================== Frame ===================================
15-
let batchQueue: (() => void)[] = [];
16-
let batchUUID = 0;
15+
let uuid = 0;
1716

18-
/** Will execute all callback before next frame but after promise */
19-
export function batchTask(callback: () => void) {
20-
batchUUID += 1;
21-
const id = batchUUID;
17+
const ids = new Set();
2218

23-
batchQueue.push(callback);
19+
/** Trigger before frame but after promise */
20+
export function beforeFrame(callback: () => void) {
21+
uuid += 1;
22+
const myId = uuid;
23+
24+
ids.add(myId);
2425

2526
const channel = new MessageChannel();
2627
channel.port1.onmessage = () => {
27-
if (id === batchUUID) {
28-
batchQueue.forEach((fn) => {
29-
fn();
30-
});
31-
batchQueue = [];
28+
if (ids.has(myId)) {
29+
ids.delete(myId);
30+
callback();
3231
}
3332
};
3433
channel.port2.postMessage(null);
34+
35+
return myId;
36+
}
37+
38+
export function cancelBeforeFrame(id: number) {
39+
ids.delete(id);
3540
}

0 commit comments

Comments
 (0)