Skip to content

Commit

Permalink
perf: slightly performance improvement
Browse files Browse the repository at this point in the history
  • Loading branch information
wellyshen committed May 25, 2021
1 parent c51eee7 commit c1ab0a0
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 55 deletions.
5 changes: 5 additions & 0 deletions .changeset/pretty-shirts-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-cool-virtual": patch
---

perf: slightly performance improvement
6 changes: 3 additions & 3 deletions app/src/App/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* import { Fragment, useState } from "react";
/* import { Fragment, useState, useCallback } from "react";
import useVirtual from "react-cool-virtual";
import { v4 as uuidv4 } from "uuid";
Expand All @@ -16,8 +16,8 @@ const getMockData = (count: number, min = 25) =>
size: min + Math.round(Math.random() * 100),
}));
const rowHeights = getMockData(1000);
const colWidths = getMockData(1000, 75);
const rowHeights = getMockData(10000);
const colWidths = getMockData(10000, 75);
export default (): JSX.Element => {
const [sz, setSz] = useState(25);
Expand Down
125 changes: 73 additions & 52 deletions src/useVirtual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,48 +165,17 @@ export default <
[overscanCount, sizeKey]
);

const [resetIsScrolling, cancelResetIsScrolling] = useDebounce(
// eslint-disable-next-line @typescript-eslint/no-use-before-define
() => updateItems(offsetRef.current),
DEBOUNCE_INTERVAL
);

const [resetOthers, cancelResetOthers] = useDebounce(() => {
userScrollRef.current = true;

const len = rosRef.current.size - measuresRef.current.length;
const iter = rosRef.current[Symbol.iterator]();
for (let i = 0; i < len; i += 1)
rosRef.current.delete(iter.next().value[0]);
}, DEBOUNCE_INTERVAL);

const updateItems = useCallback(
(offset: number, isScrolling = false) => {
const setVrItems = useCallback(
(
offset: number,
isScrolling: boolean,
oStart: number,
oStop: number,
margin: number,
innerSize: number
) => {
if (!innerRef.current) return;

if (
!hasLoadMoreOnMountRef.current &&
loadMoreRef.current &&
!(isItemLoadedRef.current && isItemLoadedRef.current(0))
)
loadMoreRef.current({
startIndex: 0,
stopIndex: loadMoreThreshold - 1,
loadIndex: 0,
scrollOffset: offset,
userScroll: userScrollRef.current,
});

hasLoadMoreOnMountRef.current = true;

if (!itemCount) {
setItems([]);
return;
}

const { oStart, oStop, vStart, vStop, margin, innerSize } =
getCalcData(offset);

innerRef.current.style[marginKey] = `${margin}px`;
innerRef.current.style[sizeKey] = `${innerSize}px`;

Expand All @@ -232,7 +201,17 @@ export default <
if (measuredSize && measuredSize !== size) {
measuresRef.current[i].size = measuredSize;
measuresRef.current = getMeasures({ idx: i });
updateItems(offset, isScrolling);

const calcData = getCalcData(offset);

setVrItems(
offset,
isScrolling,
calcData.oStart,
calcData.oStop,
calcData.margin,
calcData.innerSize
);
}

rosRef.current.get(target)?.disconnect();
Expand All @@ -247,6 +226,51 @@ export default <
? nextItems
: prevItems
);
},
[getCalcData, getMeasures, itemSizeKey, marginKey, sizeKey, useIsScrolling]
);

const [resetIsScrolling, cancelResetIsScrolling] = useDebounce(
// eslint-disable-next-line @typescript-eslint/no-use-before-define
() => handleScroll(offsetRef.current),
DEBOUNCE_INTERVAL
);

const [resetOthers, cancelResetOthers] = useDebounce(() => {
userScrollRef.current = true;

const len = rosRef.current.size - measuresRef.current.length;
const iter = rosRef.current[Symbol.iterator]();
for (let i = 0; i < len; i += 1)
rosRef.current.delete(iter.next().value[0]);
}, DEBOUNCE_INTERVAL);

const handleScroll = useCallback(
(offset: number, isScrolling = false) => {
if (
!hasLoadMoreOnMountRef.current &&
loadMoreRef.current &&
!(isItemLoadedRef.current && isItemLoadedRef.current(0))
)
loadMoreRef.current({
startIndex: 0,
stopIndex: loadMoreThreshold - 1,
loadIndex: 0,
scrollOffset: offset,
userScroll: userScrollRef.current,
});

hasLoadMoreOnMountRef.current = true;

if (!itemCount) {
setItems([]);
return;
}

const { oStart, oStop, vStart, vStop, margin, innerSize } =
getCalcData(offset);

setVrItems(offset, isScrolling, oStart, oStop, margin, innerSize);

if (!isScrolling) return;

Expand Down Expand Up @@ -285,16 +309,13 @@ export default <
},
[
getCalcData,
getMeasures,
itemCount,
itemSizeKey,
loadMoreRef,
loadMoreThreshold,
marginKey,
onScrollRef,
resetIsScrolling,
resetOthers,
sizeKey,
setVrItems,
useIsScrolling,
]
);
Expand Down Expand Up @@ -408,7 +429,7 @@ export default <

outerRectRef.current = rect;
measuresRef.current = getMeasures({ skipCache: true });
updateItems(offsetRef.current);
handleScroll(offsetRef.current);

const ratio =
!isSameWidth &&
Expand All @@ -418,18 +439,18 @@ export default <

if (ratio) scrollTo(offsetRef.current * ratio);
},
[itemCount, getMeasures, scrollTo, updateItems]
[itemCount, getMeasures, handleScroll, scrollTo]
);

useIsoLayoutEffect(() => {
const { current: outer } = outerRef;

if (!outer) return () => null;

const handleScroll = ({ target }: Event) =>
updateItems((target as O)[scrollKey], true);
const scrollHandler = ({ target }: Event) =>
handleScroll((target as O)[scrollKey], true);

outer.addEventListener("scroll", handleScroll, { passive: true });
outer.addEventListener("scroll", scrollHandler, { passive: true });

const ros = rosRef.current;

Expand All @@ -441,12 +462,12 @@ export default <
scrollRafRef.current = undefined;
}

outer.removeEventListener("scroll", handleScroll);
outer.removeEventListener("scroll", scrollHandler);

ros.forEach((ro) => ro.disconnect());
ros.clear();
};
}, [cancelResetIsScrolling, cancelResetOthers, scrollKey, updateItems]);
}, [cancelResetIsScrolling, cancelResetOthers, handleScroll, scrollKey]);

return { outerRef, innerRef, items, scrollTo, scrollToItem };
};

0 comments on commit c1ab0a0

Please sign in to comment.