Closed9

TanStack Virtualの素振り

ikuma-tikuma-t

https://tanstack.com/virtual/v3/docs/guide/introduction

  • tanstack virtualは Headless UIライブラリ
  • 中核にあるのがVirtualizer

以下公式のサンプルまんま

import { useVirtualizer } from '@tanstack/react-virtual';

function App() {
  // The scrollable element for your list
  const parentRef = React.useRef()

  // The virtualizer
  const rowVirtualizer = useVirtualizer({
    count: 10000,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 35,
  })

  return (
    <>
      {/* The scrollable element for your list */}
      <div
        ref={parentRef}
        style={{
          height: `400px`,
          overflow: 'auto', // Make it scroll!
        }}
      >
        {/* The large inner element to hold all of the items */}
        <div
          style={{
            height: `${rowVirtualizer.getTotalSize()}px`,
            width: '100%',
            position: 'relative',
          }}
        >
          {/* Only the visible items in the virtualizer, manually positioned to be in view */}
          {rowVirtualizer.getVirtualItems().map((virtualItem) => (
            <div
              key={virtualItem.key}
              style={{
                position: 'absolute',
                top: 0,
                left: 0,
                width: '100%',
                height: `${virtualItem.size}px`,
                transform: `translateY(${virtualItem.start}px)`,
              }}
            >
              Row {virtualItem.index}
            </div>
          ))}
        </div>
      </div>
    </>
  )
}

気になったこと

  • getTotalSize()っていうAPIがあるのか
  • virtualItem.sizeとかはどうやって計算しているんだ?
ikuma-tikuma-t

https://tanstack.com/virtual/v3/docs/adapters/react-virtual

ReactのAPIは2つ。

function useVirtualizer<TScrollElement, TItemElement = unknown>(
  options: PartialKeys<
    VirtualizerOptions<TScrollElement, TItemElement>,
    'observeElementRect' | 'observeElementOffset' | 'scrollToFn'
  >,
): Virtualizer<TScrollElement, TItemElement>
function useWindowVirtualizer<TItemElement = unknown>(
  options: PartialKeys<
    VirtualizerOptions<Window, TItemElement>,
    | 'getScrollElement'
    | 'observeElementRect'
    | 'observeElementOffset'
    | 'scrollToFn'
  >,
): Virtualizer<Window, TItemElement>

https://github.com/TanStack/virtual/blob/beta/packages/react-virtual/src/index.tsx

ikuma-tikuma-t

Virtualizer

https://tanstack.com/virtual/v3/docs/api/virtualizer

必須なのは、要素の総数と、スクロールを行う要素と、推定サイズだけ。react-windowより少ないな。

getTotalSizeは各要素のサイズの合計を返してくれるのか。これはreact-windowより使いやすいかも。

Returns the total size in pixels for the virtualized items. This measurement will incrementally change if you choose to dynamically measure your elements as they are rendered.

ikuma-tikuma-t

VirtualItem

https://tanstack.com/virtual/v3/docs/api/virtual-item

こっちは仮想リストの各要素。先ほどのsizeについては以下のように説明がある。

The size of the item. This is usually mapped to a css property like width/height. Before an item is measured vit the VirtualItem.measureElement method, this will be the estimated size returned from your estimateSize virtualizer option. After an item is measured (if you choose to measure it at all), this value will be the number returned by your measureElement virtualizer option (which by default is configured to measure elements with getBoundingClientRect()).

最初はestimatedSizeで取得して、その後はmeasureElementオプションに則って取得する。デフォルトではgetBoundingClientRectで取得する。

https://developer.mozilla.org/ja/docs/Web/API/Element/getBoundingClientRect

ikuma-tikuma-t

やっぱり、sizeに関しての説明の

After an item is measured (if you choose to measure it at all), this value will be the number returned by your measureElement virtualizer option (which by default is configured to measure elements with getBoundingClientRect()).

ってのがよくわからないな。if you choose to measure it at allっていうのが何を指しているのか。
measureオプション自体はあるけど、booleanかと思ったらただのfunctionだもんな。

このスクラップは2024/02/11にクローズされました