Skip to content

Instantly share code, notes, and snippets.

@lucassshanks
Created November 14, 2024 08:59
Show Gist options
  • Save lucassshanks/078d458b189dabbc2da8fb22167dc1e1 to your computer and use it in GitHub Desktop.
Save lucassshanks/078d458b189dabbc2da8fb22167dc1e1 to your computer and use it in GitHub Desktop.
Use react-window to limit the amount of items rendered in the dom in TS. The onHover will lag due to how react-select computes whether an element should be highlighted or not so a CSS solution is needed to solve this. Also included some example of data fetching. Designed for https://github.com/JedWatson/react-select/issues/3128
import React, { useEffect, useState } from 'react'
import ReactSelect, { createFilter, MenuListProps, OptionProps } from 'react-select'
import { FixedSizeList as List, ListChildComponentProps } from 'react-window'
type OptionType = {
label: string
value: string
}
export const ReactWindowSelectExample = () => {
return (
<ReactSelect
onChange={handleOnChange}
options={Options}
components={{ MenuList, Option }}
filterOption={createFilter({ ignoreAccents: false })} // To improve performance on filtering
/>
)
}
const MenuList = (props: MenuListProps<OptionType, false>) => {
const itemHeight = 35
const { options, children, maxHeight, getValue } = props
const [value] = getValue()
const initialOffset = options.indexOf(value) * itemHeight
return Array.isArray(children) ? (
<div style={{ paddingTop: 4 }}>
<List
height={maxHeight}
itemCount={children.length}
itemSize={itemHeight}
initialScrollOffset={initialOffset}
width="100%"
>
{({ index, style }: ListChildComponentProps) => <div style={{ ...style }}>{children[index]}</div>}
</List>
</div>
) : null
}
const Option = (props: OptionProps<OptionType>) => {
const { children, innerProps, getStyles, isSelected } = props
delete props.innerProps.onMouseMove
delete props.innerProps.onMouseOver
const [isHovered, setIsHovered] = useState(false)
const [isPressed, setIsPressed] = useState(false)
// Emulate default react-select styles
const customStyles = {
...getStyles('option', props),
...(isSelected || isHovered || isPressed
? {
backgroundColor: isSelected ? '#abbde9' : isPressed ? '#B2D4FF' : '#DDEBFF',
}
: {}),
color: isSelected ? 'white' : undefined,
}
return (
<div
style={customStyles as React.CSSProperties}
role="button"
id={innerProps.id}
tabIndex={innerProps.tabIndex}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onMouseDown={() => setIsPressed(true)}
onMouseUp={() => setIsPressed(false)}
onClick={innerProps.onClick}
onKeyDown={innerProps.onKeyDown}
>
{children}
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment