From 2ed3d82e9d4a183682c9a05a8b2dd7370731ecac Mon Sep 17 00:00:00 2001 From: inokawa <48897392+inokawa@users.noreply.github.com> Date: Fri, 6 Dec 2024 01:47:49 +0900 Subject: [PATCH] Refactor state update on render --- src/core/scroller.ts | 6 +++--- src/core/store.ts | 29 ++++++++++++++++------------- src/react/VGrid.tsx | 8 ++------ src/react/Virtualizer.tsx | 8 ++------ src/react/WindowVirtualizer.tsx | 4 +--- src/solid/Virtualizer.tsx | 8 ++------ src/solid/WindowVirtualizer.tsx | 4 +--- src/svelte/Virtualizer.svelte | 8 ++------ src/svelte/WindowVirtualizer.svelte | 4 +--- 9 files changed, 30 insertions(+), 49 deletions(-) diff --git a/src/core/scroller.ts b/src/core/scroller.ts index 8bf72900..92ed704f 100644 --- a/src/core/scroller.ts +++ b/src/core/scroller.ts @@ -334,7 +334,7 @@ export const createScroller = ( scheduleImperativeScroll(() => offset); }, $scrollToIndex(index, { align, smooth, offset = 0 } = {}) { - index = clamp(index, 0, store.$getItemsLength() - 1); + index = clamp(index, 0, store._getItemsLength() - 1); if (align === "nearest") { const itemOffset = store.$getItemOffset(index); @@ -356,7 +356,7 @@ export const createScroller = ( scheduleImperativeScroll(() => { return ( offset + - store.$getStartSpacerSize() + + store._getStartSpacerSize() + store.$getItemOffset(index) + (align === "end" ? store.$getItemSize(index) - store.$getViewportSize() @@ -542,7 +542,7 @@ export const createWindowScroller = ( $scrollToIndex(index, { align, smooth, offset = 0 } = {}) { if (!containerElement) return; - index = clamp(index, 0, store.$getItemsLength() - 1); + index = clamp(index, 0, store._getItemsLength() - 1); if (align === "nearest") { const itemOffset = store.$getItemOffset(index); diff --git a/src/core/store.ts b/src/core/store.ts index d765be26..a1bb913e 100644 --- a/src/core/store.ts +++ b/src/core/store.ts @@ -106,11 +106,11 @@ export type VirtualStore = { $isUnmeasuredItem(index: number): boolean; $getItemOffset(index: number): number; $getItemSize(index: number): number; - $getItemsLength(): number; + _getItemsLength(): number; $getScrollOffset(): number; $isScrolling(): boolean; $getViewportSize(): number; - $getStartSpacerSize(): number; + _getStartSpacerSize(): number; $getTotalSize(): number; $getJumpCount(): number; _flushJump(): [number, boolean]; @@ -219,11 +219,11 @@ export const createVirtualStore = ( }, $getItemOffset: getItemOffset, $getItemSize: getItemSize, - $getItemsLength: () => cache._length, + _getItemsLength: () => cache._length, $getScrollOffset: () => scrollOffset, $isScrolling: () => _scrollDirection !== SCROLL_IDLE, $getViewportSize: () => viewportSize, - $getStartSpacerSize: () => startSpacerSize, + _getStartSpacerSize: () => startSpacerSize, $getTotalSize: getTotalSize, $getJumpCount: () => jumpCount, _flushJump: () => { @@ -397,15 +397,18 @@ export const createVirtualStore = ( break; } case ACTION_ITEMS_LENGTH_CHANGE: { - if (payload[1]) { - applyJump(updateCacheLength(cache, payload[0], true)); - _scrollMode = SCROLL_BY_SHIFT; - mutated = UPDATE_VIRTUAL_STATE; - } else { - updateCacheLength(cache, payload[0]); - // https://github.com/inokawa/virtua/issues/552 - // https://github.com/inokawa/virtua/issues/557 - mutated = UPDATE_VIRTUAL_STATE; + const [length, isShift] = payload; + if (cache._length !== length) { + if (isShift) { + applyJump(updateCacheLength(cache, length, true)); + _scrollMode = SCROLL_BY_SHIFT; + mutated = UPDATE_VIRTUAL_STATE; + } else { + updateCacheLength(cache, length); + // https://github.com/inokawa/virtua/issues/552 + // https://github.com/inokawa/virtua/issues/557 + mutated = UPDATE_VIRTUAL_STATE; + } } break; } diff --git a/src/react/VGrid.tsx b/src/react/VGrid.tsx index cd4f9c60..e93739a8 100644 --- a/src/react/VGrid.tsx +++ b/src/react/VGrid.tsx @@ -240,12 +240,8 @@ export const VGrid = forwardRef( ]; }); // The elements length and cached items length are different just after element is added/removed. - if (rowCount !== vStore.$getItemsLength()) { - vStore.$update(ACTION_ITEMS_LENGTH_CHANGE, [rowCount]); - } - if (colCount !== hStore.$getItemsLength()) { - hStore.$update(ACTION_ITEMS_LENGTH_CHANGE, [colCount]); - } + vStore.$update(ACTION_ITEMS_LENGTH_CHANGE, [rowCount]); + hStore.$update(ACTION_ITEMS_LENGTH_CHANGE, [colCount]); const vRerender = useRerender(vStore); const hRerender = useRerender(hStore); diff --git a/src/react/Virtualizer.tsx b/src/react/Virtualizer.tsx index e203b8ef..46b86fe8 100644 --- a/src/react/Virtualizer.tsx +++ b/src/react/Virtualizer.tsx @@ -219,12 +219,8 @@ export const Virtualizer = forwardRef( }); // The elements length and cached items length are different just after element is added/removed. - if (count !== store.$getItemsLength()) { - store.$update(ACTION_ITEMS_LENGTH_CHANGE, [count, shift]); - } - if (startMargin !== store.$getStartSpacerSize()) { - store.$update(ACTION_START_OFFSET_CHANGE, startMargin); - } + store.$update(ACTION_ITEMS_LENGTH_CHANGE, [count, shift]); + store.$update(ACTION_START_OFFSET_CHANGE, startMargin); const rerender = useRerender(store); diff --git a/src/react/WindowVirtualizer.tsx b/src/react/WindowVirtualizer.tsx index e8222b69..98f42038 100644 --- a/src/react/WindowVirtualizer.tsx +++ b/src/react/WindowVirtualizer.tsx @@ -170,9 +170,7 @@ export const WindowVirtualizer = forwardRef< ]; }); // The elements length and cached items length are different just after element is added/removed. - if (count !== store.$getItemsLength()) { - store.$update(ACTION_ITEMS_LENGTH_CHANGE, [count, shift]); - } + store.$update(ACTION_ITEMS_LENGTH_CHANGE, [count, shift]); const rerender = useRerender(store); diff --git a/src/solid/Virtualizer.tsx b/src/solid/Virtualizer.tsx index f88c3776..c2897dbc 100644 --- a/src/solid/Virtualizer.tsx +++ b/src/solid/Virtualizer.tsx @@ -242,9 +242,7 @@ export const Virtualizer = (props: VirtualizerProps): JSX.Element => { on( () => props.data.length, (count) => { - if (count !== store.$getItemsLength()) { - store.$update(ACTION_ITEMS_LENGTH_CHANGE, [count, props.shift]); - } + store.$update(ACTION_ITEMS_LENGTH_CHANGE, [count, props.shift]); } ) ); @@ -253,9 +251,7 @@ export const Virtualizer = (props: VirtualizerProps): JSX.Element => { on( () => props.startMargin || 0, (value) => { - if (value !== store.$getStartSpacerSize()) { - store.$update(ACTION_START_OFFSET_CHANGE, value); - } + store.$update(ACTION_START_OFFSET_CHANGE, value); } ) ); diff --git a/src/solid/WindowVirtualizer.tsx b/src/solid/WindowVirtualizer.tsx index 708fccaa..6e4fd830 100644 --- a/src/solid/WindowVirtualizer.tsx +++ b/src/solid/WindowVirtualizer.tsx @@ -181,9 +181,7 @@ export const WindowVirtualizer = ( on( () => props.data.length, (len) => { - if (len !== store.$getItemsLength()) { - store.$update(ACTION_ITEMS_LENGTH_CHANGE, [len, props.shift]); - } + store.$update(ACTION_ITEMS_LENGTH_CHANGE, [len, props.shift]); } ) ); diff --git a/src/svelte/Virtualizer.svelte b/src/svelte/Virtualizer.svelte index 7c510ab5..4271d73c 100644 --- a/src/svelte/Virtualizer.svelte +++ b/src/svelte/Virtualizer.svelte @@ -86,15 +86,11 @@ }); $effect.pre(() => { - if (data.length !== store.$getItemsLength()) { - store.$update(ACTION_ITEMS_LENGTH_CHANGE, [data.length, shift]); - } + store.$update(ACTION_ITEMS_LENGTH_CHANGE, [data.length, shift]); }); $effect.pre(() => { - if (startMargin !== store.$getStartSpacerSize()) { - store.$update(ACTION_START_OFFSET_CHANGE, startMargin); - } + store.$update(ACTION_START_OFFSET_CHANGE, startMargin); }); let prevJumpCount: number | undefined; diff --git a/src/svelte/WindowVirtualizer.svelte b/src/svelte/WindowVirtualizer.svelte index 6c148a50..b79ee112 100644 --- a/src/svelte/WindowVirtualizer.svelte +++ b/src/svelte/WindowVirtualizer.svelte @@ -78,9 +78,7 @@ }); $effect.pre(() => { - if (data.length !== store.$getItemsLength()) { - store.$update(ACTION_ITEMS_LENGTH_CHANGE, [data.length, shift]); - } + store.$update(ACTION_ITEMS_LENGTH_CHANGE, [data.length, shift]); }); let prevJumpCount: number | undefined;