reactjs 如何虚拟化React-Select的选项?

3phpmpom  于 2023-11-18  发布在  React
关注(0)|答案(1)|浏览(160)

我一直在尝试在React-Select组件中实现虚拟化,但没有成功。我尝试使用的每个虚拟化包都有一些我无法解决的破坏性错误,确切地说:

  • react-select-virtualized:图形错误,选择根本不起作用
  • react-virtualized:出于某种原因,仍然有点不稳定,也打破了图形错误(像任何文本,将在第二行显示在下一个选项)
  • react-window:根本无法让它工作
  • react-virtual:非常不稳定(可能根本不工作)
  • react-virtuoso:仍然非常不稳定,无法使用(尽管比正常情况稍好,但对于prod来说还不够好)。

这可能是因为我缺乏经验而搞砸了一些事情,但即使直接复制粘贴其他人的解决方案,我最终也会出现错误。我相信这与上面的大多数虚拟化包没有完全适应选择v5或TypeScript或React 18等有关。
任何帮助将不胜感激!!提前感谢您:)

wmvff8tz

wmvff8tz1#

**与这一点相关的答案:**react-virtualized:出于某种原因,仍然有点不稳定,也打破了图形错误(就像第二行中的任何文本显示在下一个选项中一样)

为了防止第二行出现在下一个选项中,您需要一个CellMeasurerCache
当列表大小(宽度)改变时,它将自动重新计算可见框架中每行的高度。
当然,这不是一个完美的解决方案,但它符合您的要求

import React, { useMemo } from 'react'
import AsyncSelect from 'react-select/async'
import { List, AutoSizer, CellMeasurer, CellMeasurerCache } from 'react-virtualized'
import type { MenuListProps, GroupBase } from 'react-select'
import type { ListRowProps } from 'react-virtualized'

type ListOption = {
  label: string
  value: string
}

const VirtualizedList = ({ children }: MenuListProps<ListOption, false, GroupBase<ListOption>>) => {
  const rows = children

  const cellCache = useMemo(() => {
    return new CellMeasurerCache({
      fixedWidth: true,
      defaultHeight: 30
    })
  }, [])

  if (!Array.isArray(rows)) {
    // For children like: "Loading" or "No Options" provided by 'react-select'
    return <>{children}</>
  }

  const rowRenderer = ({ key, parent, index, style }: ListRowProps) => (
    <CellMeasurer cache={cellCache} key={key} columnIndex={0} rowIndex={index} parent={parent}>
      <div key={key} style={style}>
        {rows[index]}
      </div>
    </CellMeasurer>
  )

  return (
    <div style={{ height: '300px' }}>
      <AutoSizer>
        {({ width, height }) => (
          <List
            width={width}
            height={height}
            deferredMeasurementCache={cellCache}
            rowHeight={cellCache.rowHeight}
            rowCount={rows.length}
            rowRenderer={rowRenderer}
          />
        )}
      </AutoSizer>
    </div>
  )
}

export const Example = () => {
  return (
    <div>
      <AsyncSelect
        cacheOptions
        components={{ MenuList: VirtualizedList }}
        defaultOptions={'YOUR DEFAULT DATA'}
        loadOptions={'YOUR DATA FROM SOMEWHERE'}
        styles={{
          menu: ({ position, fontWeight, ...provided }) => ({
            ...provided,
            position: 'static'
          })
        }}
      />
    </div>
  )
}

字符串
更改行宽触发缓存重新计算的示例

相关问题