Skip to content

Commit

Permalink
feat(dropdown): virtualize options list for better performance of lon…
Browse files Browse the repository at this point in the history
…g lists

Use `react-virtuoso` to virtualize the option items in the dropdown. This is done to reduce the
amount of time to render the initial view and process updates.

fix #184
  • Loading branch information
dawsonbooth committed Aug 9, 2021
1 parent 0004a9b commit 805ed04
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 15 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"nanoid": "^3.1.20",
"polished": "^4.1.1",
"react-portal": "^4.2.1",
"react-virtuoso": "^1.10.5",
"src": "^1.1.2"
},
"peerDependencies": {
Expand Down
51 changes: 36 additions & 15 deletions src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Icon from '@mdi/react';
import { mdiCheck, mdiClose, mdiMenuDown, mdiMenuUp } from '@mdi/js';
import { shade, tint, getLuminance, darken, readableColor } from 'polished';

import { Components, Virtuoso } from 'react-virtuoso';
import { useTheme } from '../../context';
import Button from '../Button/Button';
import variants from '../../enums/variants';
Expand Down Expand Up @@ -86,7 +87,7 @@ const OptionsContainer = styled(Div)`
position: absolute;
top: 100%;
left: 0px;
max-height: 10rem;
height: 10rem;
overflow-y: auto;
width: 15rem;
${
Expand Down Expand Up @@ -481,6 +482,34 @@ const Dropdown = ({
</>
);

const VirtuosoComponents = useMemo(
() => ({
Scroller: React.forwardRef(({ children }, listRef) => (
<StyledOptionsContainer
color={defaultedColor}
variant={optionsVariant}
role="listbox"
ref={mergeRefs([
optionsContainerRef,
optionsContainerInternalRef,
optionsScrollListenerCallbackRef,
listRef as React.RefObject<HTMLDivElement>,
])}
{...optionsContainerProps}
>
{children}
</StyledOptionsContainer>
)),
}),
[
defaultedColor,
optionsContainerProps,
optionsContainerRef,
optionsScrollListenerCallbackRef,
optionsVariant,
],
);

return (
<StyledContainer
id={`${name}-container`}
Expand Down Expand Up @@ -544,18 +573,10 @@ const Dropdown = ({
{closeIcons}
</Button>
{isOpen && (
<StyledOptionsContainer
color={defaultedColor}
variant={optionsVariant}
role="listbox"
ref={mergeRefs([
optionsContainerRef,
optionsContainerInternalRef,
optionsScrollListenerCallbackRef,
])}
{...optionsContainerProps}
>
{options.map(option => (
<Virtuoso
data={options}
components={VirtuosoComponents as Components}
itemContent={(index, option) => (
<StyledOptionItem
id={`${name}-option-${option.id}`}
key={`${name}-option-${option.id}`}
Expand Down Expand Up @@ -583,8 +604,8 @@ const Dropdown = ({
)}
<Span>{option.optionValue}</Span>
</StyledOptionItem>
))}
</StyledOptionsContainer>
)}
/>
)}
</StyledContainer>
);
Expand Down
23 changes: 23 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4083,6 +4083,18 @@
dependencies:
eslint-visitor-keys "^1.1.0"

"@virtuoso.dev/react-urx@^0.2.5":
version "0.2.6"
resolved "https://registry.yarnpkg.com/@virtuoso.dev/react-urx/-/react-urx-0.2.6.tgz#e1d8bc717723b2fc23d80ea4e07703dbc276448b"
integrity sha512-+PLQ2iWmSH/rW7WGPEf+Kkql+xygHFL43Jij5aREde/O9mE0OFFGqeetA2a6lry3LDVWzupPntvvWhdaYw0TyA==
dependencies:
"@virtuoso.dev/urx" "^0.2.6"

"@virtuoso.dev/urx@^0.2.5", "@virtuoso.dev/urx@^0.2.6":
version "0.2.6"
resolved "https://registry.yarnpkg.com/@virtuoso.dev/urx/-/urx-0.2.6.tgz#0028c49e52037e673993900d32abea83262fbd53"
integrity sha512-EKJ0WvJgWaXIz6zKbh9Q63Bcq//p8OHXHbdz4Fy+ruhjJCyI8ADE8E5gwSqBoUchaiYlgwKrT+sX4L2h/H+hMg==

"@webassemblyjs/ast@1.11.1":
version "1.11.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
Expand Down Expand Up @@ -15903,6 +15915,15 @@ react-use-measure@^2.0.3:
dependencies:
debounce "^1.2.0"

react-virtuoso@^1.10.5:
version "1.10.5"
resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-1.10.5.tgz#8c8da1c3de1e6214437cb2bcaf07c8df19013316"
integrity sha512-UE1KmgjDbJ6pR/ymEgCeOI1mX9ni2I6MwQpQJ6ycRBovaobb0MVBbn7NM3KDE8HiaRXaRm+y0rq9xNhCX1GbsA==
dependencies:
"@virtuoso.dev/react-urx" "^0.2.5"
"@virtuoso.dev/urx" "^0.2.5"
resize-observer-polyfill "^1.5.1"

react@^16.13.1:
version "16.14.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"
Expand Down Expand Up @@ -18825,8 +18846,10 @@ watchpack@^1.6.0, watchpack@^1.7.4:
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453"
integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==
dependencies:
chokidar "^3.4.1"
graceful-fs "^4.1.2"
neo-async "^2.5.0"
watchpack-chokidar2 "^2.0.1"
optionalDependencies:
chokidar "^3.4.1"
watchpack-chokidar2 "^2.0.1"
Expand Down

0 comments on commit 805ed04

Please sign in to comment.