From e1dfe6aed1fb24aa09f07f766daf2e52936b35bc Mon Sep 17 00:00:00 2001 From: Tobias Fried Date: Fri, 17 Jul 2020 13:24:00 -0400 Subject: [PATCH] IconGrid: experiment with various list virtualization libraries --- package.json | 5 + src/components/IconGrid/IconGrid.css | 6 +- src/components/IconGrid/IconGrid.tsx | 98 ++++++++++++++++--- src/components/IconGrid/IconGridRL.tsx | 34 +++++++ .../IconGrid/IconGridVirtualized.tsx | 34 +++++++ yarn.lock | 78 ++++++++++++++- 6 files changed, 238 insertions(+), 17 deletions(-) create mode 100644 src/components/IconGrid/IconGridRL.tsx create mode 100644 src/components/IconGrid/IconGridVirtualized.tsx diff --git a/package.json b/package.json index 6157096..97010b1 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,14 @@ "@types/node": "^12.0.0", "@types/react": "^16.9.43", "@types/react-dom": "^16.9.8", + "@types/react-list": "^0.8.5", + "@types/react-virtualized": "^9.21.10", "react": "^16.13.1", "react-dom": "^16.13.1", + "react-list": "^0.8.15", "react-scripts": "3.4.1", + "react-virtual": "^2.2.1", + "react-virtualized": "^9.21.2", "recoil": "^0.0.10", "typescript": "^3.9.6" }, diff --git a/src/components/IconGrid/IconGrid.css b/src/components/IconGrid/IconGrid.css index 5049591..1955de9 100644 --- a/src/components/IconGrid/IconGrid.css +++ b/src/components/IconGrid/IconGrid.css @@ -5,9 +5,13 @@ .grid-item { margin: 4px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; background-color: aquamarine; filter: grayscale(100%); - transition: 0.5s ease; + transition: filter 0.5s ease; } .grid-item:hover { diff --git a/src/components/IconGrid/IconGrid.tsx b/src/components/IconGrid/IconGrid.tsx index 9483060..e3a4402 100644 --- a/src/components/IconGrid/IconGrid.tsx +++ b/src/components/IconGrid/IconGrid.tsx @@ -1,27 +1,101 @@ -import React from "react"; +import React, { useRef, useCallback, useMemo } from "react"; import { useRecoilValue } from "recoil"; +import { useVirtual } from "react-virtual"; import { filteredQueryResultsSelector } from "../../state/selectors"; +import { iconColorAtom, iconSizeAtom } from "../../state/atoms"; import "./IconGrid.css"; type IconGridProps = {}; +const COLUMN_COUNT = 5; + const IconGrid: React.FC = () => { + const parentRef = useRef(null); + const color = useRecoilValue(iconColorAtom); + const size = useRecoilValue(iconSizeAtom); const filteredQueryResults = useRecoilValue(filteredQueryResultsSelector); + // const categorizedQueryResults = useRecoilValue(categorizedQueryResultsSelector); + // console.log(categorizedQueryResults); + + // const rowVirtualizer = useVirtual({ + // size: useMemo(() => Math.ceil(filteredQueryResults.length / COLUMN_COUNT), [ + // filteredQueryResults, + // ]), + // parentRef, + // estimateSize: useCallback(() => 220 * COLUMN_COUNT, []), + // }); + + const rowVirtualizer = useVirtual({ + size: useMemo(() => Math.ceil(filteredQueryResults.length / COLUMN_COUNT), [ + filteredQueryResults, + ]), + parentRef, + estimateSize: useCallback(() => 240, []), + overscan: 5, + }); + + const columnVirtualizer = useVirtual({ + horizontal: true, + size: COLUMN_COUNT, + parentRef, + estimateSize: useCallback(() => 160, []), + }); return ( -
- {filteredQueryResults.map((icon) => ( -
- {`${icon.name} -
{icon.name}
+ <> +
+
+ {rowVirtualizer.virtualItems.map((virtualRow) => ( + + {columnVirtualizer.virtualItems.map((virtualColumn) => ( +
+ {(function () { + const icon = + filteredQueryResults[ + virtualRow.index * COLUMN_COUNT + virtualColumn.index + ]; + if (!icon) return null; + return ( + <> + {`${icon.name} +

{icon.name}

+ + ); + })()} +
+ ))} +
+ ))}
- ))} -
+
+ ); }; diff --git a/src/components/IconGrid/IconGridRL.tsx b/src/components/IconGrid/IconGridRL.tsx new file mode 100644 index 0000000..3ce0541 --- /dev/null +++ b/src/components/IconGrid/IconGridRL.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import { useRecoilValue } from "recoil"; +import ReactList from "react-list"; + +import { filteredQueryResultsSelector } from "../../state/selectors"; +import "./IconGrid.css"; + +type IconGridProps = {}; + +const IconGridRL: React.FC = () => { + const filteredQueryResults = useRecoilValue(filteredQueryResultsSelector); + + const renderItem = (index: number, key: number | string) => { + const icon = filteredQueryResults[index]; + return ( +
+ {`${icon.name} +
{icon.name}
+
+ ); + }; + + return ( +
+ +
+ ); +}; + +export default IconGridRL; diff --git a/src/components/IconGrid/IconGridVirtualized.tsx b/src/components/IconGrid/IconGridVirtualized.tsx new file mode 100644 index 0000000..7121f58 --- /dev/null +++ b/src/components/IconGrid/IconGridVirtualized.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import { useRecoilValue } from "recoil"; +import { Grid } from "react-virtualized"; + +import { filteredQueryResultsSelector } from "../../state/selectors"; +import "./IconGrid.css"; + +type IconGridProps = {}; + +const COLUMN_COUNT = 5; + +export default class IconGridVirtualized extends React.PureComponent { + constructor(props: IconGridProps) { + super(props); + } + + render() { + const filteredQueryResults = useRecoilValue(filteredQueryResultsSelector); + + const cellRenderer = () =>
+ + return ( + + ) + } +} diff --git a/yarn.lock b/yarn.lock index d5923e6..0aae727 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1067,7 +1067,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.1", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.1", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c" integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg== @@ -1328,6 +1328,11 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@reach/observe-rect@^1.1.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2" + integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ== + "@sheerun/mutationobserver-shim@^0.3.2": version "0.3.3" resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz#5405ee8e444ed212db44e79351f0c70a582aae25" @@ -1614,6 +1619,21 @@ dependencies: "@types/react" "*" +"@types/react-list@^0.8.5": + version "0.8.5" + resolved "https://registry.yarnpkg.com/@types/react-list/-/react-list-0.8.5.tgz#813257a341788917541d0e4f631388aa1aa55190" + integrity sha512-DnVqL0peKL/kCyTWHW4JzNLP/hAgAfoSeJdInq4bbRVZAjwzpJ5M7E7xpNelS6NvHRfKFp5km+Q3317hXZM1gA== + dependencies: + "@types/react" "*" + +"@types/react-virtualized@^9.21.10": + version "9.21.10" + resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.21.10.tgz#cd072dc9c889291ace2c4c9de8e8c050da8738b7" + integrity sha512-f5Ti3A7gGdLkPPFNHTrvKblpsPNBiQoSorOEOD+JPx72g/Ng2lOt4MYfhvQFQNgyIrAro+Z643jbcKafsMW2ag== + dependencies: + "@types/prop-types" "*" + "@types/react" "*" + "@types/react@*", "@types/react@^16.9.43": version "16.9.43" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.43.tgz#c287f23f6189666ee3bebc2eb8d0f84bcb6cdb6b" @@ -3000,6 +3020,11 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +clsx@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" + integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3560,7 +3585,7 @@ cssstyle@^1.0.0, cssstyle@^1.1.1: dependencies: cssom "0.3.x" -csstype@^2.2.0: +csstype@^2.2.0, csstype@^2.6.7: version "2.6.11" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.11.tgz#452f4d024149ecf260a852b025e36562a253ffc5" integrity sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw== @@ -3819,6 +3844,14 @@ dom-converter@^0.2: dependencies: utila "~0.4" +dom-helpers@^5.0.0: + version "5.1.4" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.4.tgz#4609680ab5c79a45f2531441f1949b79d6587f4b" + integrity sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^2.6.7" + dom-serializer@0: version "0.2.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" @@ -6623,7 +6656,7 @@ loglevel@^1.6.6: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -8478,7 +8511,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" -prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -8694,6 +8727,18 @@ react-is@^16.12.0, react-is@^16.8.1, react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + +react-list@^0.8.15: + version "0.8.15" + resolved "https://registry.yarnpkg.com/react-list/-/react-list-0.8.15.tgz#990d46170c426b438787800f68f017cb51840e2e" + integrity sha512-ghb0XInIVkxNW0GM+JULAeaDAjxEcCaKa6kNFPvIVC4FDFYIU24B/+gumCoCvXWuPwcUmkcVL7yZ/WLEcFjebA== + dependencies: + prop-types "15" + react-scripts@3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-3.4.1.tgz#f551298b5c71985cc491b9acf3c8e8c0ae3ada0a" @@ -8754,6 +8799,26 @@ react-scripts@3.4.1: optionalDependencies: fsevents "2.1.2" +react-virtual@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-virtual/-/react-virtual-2.2.1.tgz#639741f203b683630457836e85ddbba7a732d9b5" + integrity sha512-71wjhbm/WgFRKaaS/oAN6znUpQkdSdbRfg3jCyvgP45QAbBKH3lSiTR/nLawgqhlwGjcYp9jN94MLNW1UVoobQ== + dependencies: + "@reach/observe-rect" "^1.1.0" + ts-toolbelt "^6.4.2" + +react-virtualized@^9.21.2: + version "9.21.2" + resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.2.tgz#02e6df65c1e020c8dbf574ec4ce971652afca84e" + integrity sha512-oX7I7KYiUM7lVXQzmhtF4Xg/4UA5duSA+/ZcAvdWlTLFCoFYq1SbauJT5gZK9cZS/wdYR6TPGpX/dqzvTqQeBA== + dependencies: + babel-runtime "^6.26.0" + clsx "^1.0.1" + dom-helpers "^5.0.0" + loose-envify "^1.3.0" + prop-types "^15.6.0" + react-lifecycles-compat "^3.0.4" + react@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" @@ -10170,6 +10235,11 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== +ts-toolbelt@^6.4.2: + version "6.13.11" + resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.13.11.tgz#46260d1cff0f2d635931df8d32239b73f2ed4f8d" + integrity sha512-QmvHwAofS1MAn1ndXCn2AVhxJLipaj4tK26SrhBTiydfgKtbLlU2efpIP/8Jocrc9ynNslZqrhqAesruJMlxCQ== + tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: version "1.13.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"