Skip to content

Commit

Permalink
Change StateVersion state to number and remove jumpCount
Browse files Browse the repository at this point in the history
  • Loading branch information
inokawa committed Mar 6, 2025
1 parent 952b28b commit 5b0c55e
Show file tree
Hide file tree
Showing 12 changed files with 96 additions and 94 deletions.
14 changes: 6 additions & 8 deletions src/core/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import type {
} from "./types";
import { abs, max, min, NULL } from "./utils";

const MAX_INT_32 = 0x7fffffff;

const SCROLL_IDLE = 0;
const SCROLL_DOWN = 1;
const SCROLL_UP = 2;
Expand Down Expand Up @@ -92,7 +94,8 @@ export const isInitialMeasurementDone = (store: VirtualStore): boolean => {
type Subscriber = (sync?: boolean) => void;

/** @internal */
export type StateVersion = readonly [];
export type StateVersion =
number & {} /* hack for typescript to pretend as not falsy */;

/**
* @internal
Expand All @@ -112,7 +115,6 @@ export type VirtualStore = {
$getViewportSize(): number;
$getStartSpacerSize(): number;
$getTotalSize(): number;
$getJumpCount(): number;
_flushJump(): [number, boolean];
$subscribe(target: number, cb: Subscriber): () => void;
$update(...action: Actions): void;
Expand All @@ -131,11 +133,10 @@ export const createVirtualStore = (
shouldAutoEstimateItemSize: boolean = false
): VirtualStore => {
let isSSR = !!ssrCount;
let stateVersion: StateVersion = [];
let stateVersion: StateVersion = 1;
let viewportSize = 0;
let startSpacerSize = 0;
let scrollOffset = 0;
let jumpCount = 0;
let jump = 0;
let pendingJump = 0;
let _flushedJump = 0;
Expand Down Expand Up @@ -173,7 +174,6 @@ export const createVirtualStore = (
pendingJump += j;
} else {
jump += j;
jumpCount++;
}
}
};
Expand Down Expand Up @@ -228,7 +228,6 @@ export const createVirtualStore = (
$getViewportSize: () => viewportSize,
$getStartSpacerSize: () => startSpacerSize,
$getTotalSize: getTotalSize,
$getJumpCount: () => jumpCount,
_flushJump: () => {
_flushedJump = jump;
jump = 0;
Expand Down Expand Up @@ -429,12 +428,11 @@ export const createVirtualStore = (
}

if (mutated) {
stateVersion = [];
stateVersion = (stateVersion % MAX_INT_32) + 1;

if (shouldFlushPendingJump && pendingJump) {
jump += pendingJump;
pendingJump = 0;
jumpCount++;
}

subscribers.forEach(([target, cb]) => {
Expand Down
18 changes: 12 additions & 6 deletions src/react/VGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
forwardRef,
ReactNode,
useImperativeHandle,
useReducer,
} from "react";
import {
ACTION_ITEMS_LENGTH_CHANGE,
Expand All @@ -24,7 +25,6 @@ import { refKey } from "./utils";
import { useStatic } from "./useStatic";
import { ViewportComponentAttributes } from "./types";
import { flushSync } from "react-dom";
import { useRerender } from "./useRerender";

const genKey = (i: number, j: number) => `${i}-${j}`;

Expand Down Expand Up @@ -247,15 +247,21 @@ export const VGrid = forwardRef<VGridHandle, VGridProps>(
hStore.$update(ACTION_ITEMS_LENGTH_CHANGE, [colCount]);
}

const vRerender = useRerender(vStore);
const hRerender = useRerender(hStore);
const [vStateVersion, vRerender] = useReducer(
vStore.$getStateVersion,
undefined,
vStore.$getStateVersion
);
const [hStateVersion, hRerender] = useReducer(
hStore.$getStateVersion,
undefined,
hStore.$getStateVersion
);

const [startRowIndex, endRowIndex] = vStore.$getRange();
const [startColIndex, endColIndex] = hStore.$getRange();
const vIsScrolling = vStore.$isScrolling();
const hIsScrolling = hStore.$isScrolling();
const vJumpCount = vStore.$getJumpCount();
const hJumpCount = hStore.$getJumpCount();
const height = getScrollSize(vStore);
const width = getScrollSize(hStore);
const rootRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -295,7 +301,7 @@ export const VGrid = forwardRef<VGridHandle, VGridProps>(

useIsomorphicLayoutEffect(() => {
scroller.$fixScrollJump();
}, [vJumpCount, hJumpCount]);
}, [vStateVersion, hStateVersion]);

useImperativeHandle(ref, () => {
return {
Expand Down
11 changes: 7 additions & 4 deletions src/react/Virtualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ReactNode,
useRef,
RefObject,
useReducer,
} from "react";
import {
UPDATE_SCROLL_EVENT,
Expand All @@ -28,7 +29,6 @@ import { useStatic } from "./useStatic";
import { useLatestRef } from "./useLatestRef";
import { ListItem } from "./ListItem";
import { flushSync } from "react-dom";
import { useRerender } from "./useRerender";
import { useChildren } from "./useChildren";
import { CustomContainerComponent, CustomItemComponent } from "./types";

Expand Down Expand Up @@ -226,11 +226,14 @@ export const Virtualizer = forwardRef<VirtualizerHandle, VirtualizerProps>(
store.$update(ACTION_START_OFFSET_CHANGE, startMargin);
}

const rerender = useRerender(store);
const [stateVersion, rerender] = useReducer(
store.$getStateVersion,
undefined,
store.$getStateVersion
);

const [startIndex, endIndex] = store.$getRange();
const isScrolling = store.$isScrolling();
const jumpCount = store.$getJumpCount();
const totalSize = store.$getTotalSize();

const items: ReactElement[] = [];
Expand Down Expand Up @@ -298,7 +301,7 @@ export const Virtualizer = forwardRef<VirtualizerHandle, VirtualizerProps>(

useIsomorphicLayoutEffect(() => {
scroller.$fixScrollJump();
}, [jumpCount]);
}, [stateVersion]);

useImperativeHandle(ref, () => {
return {
Expand Down
11 changes: 7 additions & 4 deletions src/react/WindowVirtualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ReactNode,
forwardRef,
useImperativeHandle,
useReducer,
useRef,
} from "react";
import {
Expand All @@ -24,7 +25,6 @@ import { useLatestRef } from "./useLatestRef";
import { CustomContainerComponent, CustomItemComponent } from "./types";
import { ListItem } from "./ListItem";
import { flushSync } from "react-dom";
import { useRerender } from "./useRerender";
import { useChildren } from "./useChildren";

/**
Expand Down Expand Up @@ -173,11 +173,14 @@ export const WindowVirtualizer = forwardRef<
store.$update(ACTION_ITEMS_LENGTH_CHANGE, [count, shift]);
}

const rerender = useRerender(store);
const [stateVersion, rerender] = useReducer(
store.$getStateVersion,
undefined,
store.$getStateVersion
);

const [startIndex, endIndex] = store.$getRange();
const isScrolling = store.$isScrolling();
const jumpCount = store.$getJumpCount();
const totalSize = store.$getTotalSize();

const items: ReactElement[] = [];
Expand Down Expand Up @@ -221,7 +224,7 @@ export const WindowVirtualizer = forwardRef<

useIsomorphicLayoutEffect(() => {
scroller.$fixScrollJump();
}, [jumpCount]);
}, [stateVersion]);

useImperativeHandle(ref, () => {
return {
Expand Down
13 changes: 0 additions & 13 deletions src/react/useRerender.ts

This file was deleted.

16 changes: 7 additions & 9 deletions src/solid/Virtualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export const Virtualizer = <T,>(props: VirtualizerProps<T>): JSX.Element => {
const resizer = createResizer(store, horizontal);
const scroller = createScroller(store, horizontal);

const [rerender, setRerender] = createSignal(store.$getStateVersion());
const [stateVersion, setRerender] = createSignal(store.$getStateVersion());

const unsubscribeStore = store.$subscribe(UPDATE_VIRTUAL_STATE, () => {
setRerender(store.$getStateVersion());
Expand All @@ -187,17 +187,15 @@ export const Virtualizer = <T,>(props: VirtualizerProps<T>): JSX.Element => {
);

const range = createMemo<ItemsRange>((prev) => {
rerender();
stateVersion();
const next = store.$getRange();
if (prev && isSameRange(prev, next)) {
return prev;
}
return next;
});
const isScrolling = createMemo(() => rerender() && store.$isScrolling());
const totalSize = createMemo(() => rerender() && store.$getTotalSize());

const jumpCount = createMemo(() => rerender() && store.$getJumpCount());
const isScrolling = createMemo(() => stateVersion() && store.$isScrolling());
const totalSize = createMemo(() => stateVersion() && store.$getTotalSize());

onMount(() => {
if (props.ref) {
Expand Down Expand Up @@ -261,7 +259,7 @@ export const Virtualizer = <T,>(props: VirtualizerProps<T>): JSX.Element => {
);

createEffect(
on(jumpCount, () => {
on(stateVersion, () => {
scroller.$fixScrollJump();
})
);
Expand All @@ -286,11 +284,11 @@ export const Virtualizer = <T,>(props: VirtualizerProps<T>): JSX.Element => {
_range={range()}
_render={(data, index) => {
const offset = createMemo(() => {
rerender();
stateVersion();
return store.$getItemOffset(index);
});
const hide = createMemo(() => {
rerender();
stateVersion();
return store.$isUnmeasuredItem(index);
});

Expand Down
16 changes: 7 additions & 9 deletions src/solid/WindowVirtualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const WindowVirtualizer = <T,>(
const resizer = createWindowResizer(store, horizontal);
const scroller = createWindowScroller(store, horizontal);

const [rerender, setRerender] = createSignal(store.$getStateVersion());
const [stateVersion, setRerender] = createSignal(store.$getStateVersion());

const unsubscribeStore = store.$subscribe(UPDATE_VIRTUAL_STATE, () => {
setRerender(store.$getStateVersion());
Expand All @@ -140,17 +140,15 @@ export const WindowVirtualizer = <T,>(
);

const range = createMemo<ItemsRange>((prev) => {
rerender();
stateVersion();
const next = store.$getRange();
if (prev && isSameRange(prev, next)) {
return prev;
}
return next;
});
const isScrolling = createMemo(() => rerender() && store.$isScrolling());
const totalSize = createMemo(() => rerender() && store.$getTotalSize());

const jumpCount = createMemo(() => rerender() && store.$getJumpCount());
const isScrolling = createMemo(() => stateVersion() && store.$isScrolling());
const totalSize = createMemo(() => stateVersion() && store.$getTotalSize());

onMount(() => {
if (props.ref) {
Expand Down Expand Up @@ -189,7 +187,7 @@ export const WindowVirtualizer = <T,>(
);

createEffect(
on(jumpCount, () => {
on(stateVersion, () => {
scroller.$fixScrollJump();
})
);
Expand All @@ -213,11 +211,11 @@ export const WindowVirtualizer = <T,>(
_range={range()}
_render={(data, index) => {
const offset = createMemo(() => {
rerender();
stateVersion();
return store.$getItemOffset(index);
});
const hide = createMemo(() => {
rerender();
stateVersion();
return store.$isUnmeasuredItem(index);
});

Expand Down
21 changes: 10 additions & 11 deletions src/svelte/Virtualizer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
const resizer = createResizer(store, horizontal);
const scroller = createScroller(store, horizontal);
const unsubscribeStore = store.$subscribe(UPDATE_VIRTUAL_STATE, () => {
rerender = store.$getStateVersion();
stateVersion = store.$getStateVersion();
});
const unsubscribeOnScroll = store.$subscribe(UPDATE_SCROLL_EVENT, () => {
onscroll && onscroll(store.$getScrollOffset());
Expand All @@ -59,12 +59,11 @@
let containerRef: HTMLDivElement | undefined = $state();
let rerender: StateVersion = $state(store.$getStateVersion());
let stateVersion: StateVersion = $state(store.$getStateVersion());
let range = $derived(rerender && store.$getRange());
let isScrolling = $derived(rerender && store.$isScrolling());
let totalSize = $derived(rerender && store.$getTotalSize());
let jumpCount = $derived(rerender && store.$getJumpCount());
let range = $derived(stateVersion && store.$getRange());
let isScrolling = $derived(stateVersion && store.$isScrolling());
let totalSize = $derived(stateVersion && store.$getTotalSize());
onMount(() => {
const assignRef = (scrollable: HTMLElement) => {
Expand Down Expand Up @@ -97,10 +96,10 @@
}
});
let prevJumpCount: number | undefined;
let prevStateVersion: StateVersion | undefined;
$effect(() => {
if (prevJumpCount === jumpCount) return;
prevJumpCount = jumpCount;
if (prevStateVersion === stateVersion) return;
prevStateVersion = stateVersion;
scroller.$fixScrollJump();
});
Expand Down Expand Up @@ -153,8 +152,8 @@
{item}
{index}
as={itemAs}
offset={rerender && store.$getItemOffset(index)}
hide={rerender && store.$isUnmeasuredItem(index)}
offset={stateVersion && store.$getItemOffset(index)}
hide={stateVersion && store.$isUnmeasuredItem(index)}
{horizontal}
resizer={resizer.$observeItem}
/>
Expand Down
Loading

0 comments on commit 5b0c55e

Please sign in to comment.