diff options
author | eug-vs <eug-vs@keemail.me> | 2020-08-14 19:24:00 +0300 |
---|---|---|
committer | eug-vs <eug-vs@keemail.me> | 2020-08-14 19:24:17 +0300 |
commit | e4452e3e575b57031de83259bbd403faa7cdce2a (patch) | |
tree | d3e47f724def8a9397e256f4946e1aa1e43d87f4 /src/components | |
parent | f78da28da3ee30b0c458c10c97db9ae7d2c6372d (diff) | |
download | which-ui-e4452e3e575b57031de83259bbd403faa7cdce2a.tar.gz |
perf: greatly bost PollsList performance :rocket:
Get rid of unnesessary re-renders of the whole list on scroll.
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/PollsList/PollsList.tsx | 44 | ||||
-rw-r--r-- | src/components/PollsList/RenderItem.tsx | 47 |
2 files changed, 60 insertions, 31 deletions
diff --git a/src/components/PollsList/PollsList.tsx b/src/components/PollsList/PollsList.tsx index c95bfde..62273ef 100644 --- a/src/components/PollsList/PollsList.tsx +++ b/src/components/PollsList/PollsList.tsx @@ -1,41 +1,23 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { Poll } from 'which-types'; import { WindowScroller, AutoSizer, List } from 'react-virtualized'; -import PollCard from '../PollCard/PollCard'; - +import RenderItem from './RenderItem'; interface PropTypes { polls: Poll[]; mutate: (polls: Poll[], refetch: boolean) => void; } -interface RenderPropTypes { - index: number; - key: string; - style: React.CSSProperties; -} - - const PollsList: React.FC<PropTypes> = ({ polls, mutate }) => { - const RenderItem: React.FC<RenderPropTypes> = ({ index, style, key }) => { - const poll = polls[index]; - - const setPoll = (newPoll: Poll) => { - const newPolls = [...polls]; - newPolls[index] = newPoll; - - // Force-update list-size so everything re-renders - mutate([], false); - mutate(newPolls, false); - }; - - return ( - // To re-render on list resize, add this info to key - <div key={`${key}-${poll._id}-${polls.length}`} style={style}> - <PollCard poll={poll} setPoll={setPoll} /> - </div> - ); - }; + const rowRenderer = useCallback(({ index, style, key }) => ( + <RenderItem + polls={polls} + mutate={mutate} + index={index} + style={style} + key={key} + /> + ), [polls, mutate]); return ( <WindowScroller> @@ -56,11 +38,11 @@ const PollsList: React.FC<PropTypes> = ({ polls, mutate }) => { onScroll={onChildScroll} rowCount={polls.length} rowHeight={550} - rowRenderer={RenderItem} + rowRenderer={rowRenderer} scrollTop={scrollTop} width={width} containerStyle={{ pointerEvents: 'auto' }} - overscanRowCount={1} + overscanRowCount={2} /> </div> )} diff --git a/src/components/PollsList/RenderItem.tsx b/src/components/PollsList/RenderItem.tsx new file mode 100644 index 0000000..900dae6 --- /dev/null +++ b/src/components/PollsList/RenderItem.tsx @@ -0,0 +1,47 @@ +import React, { useCallback } from 'react'; +import { Poll } from 'which-types'; +import PollCard from '../PollCard/PollCard'; + + +interface PropTypes { + polls: Poll[]; + mutate: (polls: Poll[], refetch: boolean) => void; + index: number; + style: React.CSSProperties; + key: string; +} + +const compareProps = (oldProps: PropTypes, newProps: PropTypes) => { + if (oldProps.key !== newProps.key) return false; + if (oldProps.index !== newProps.index) return false; + if (oldProps.polls !== newProps.polls) return false; + // TODO: uncomment line below to listen to style updates + // if (JSON.stringify(oldProps.style)!== JSON.stringify(newProps.style)) return false; + return true; +}; + +const RenderItem: React.FC<PropTypes> = React.memo(({ + polls, mutate, index, style, key +}) => { + const poll = polls[index]; + + const setPoll = useCallback((newPoll: Poll) => { + const newPolls = [...polls]; + newPolls[index] = newPoll; + + // Force-update list-size so everything re-renders + mutate([], false); + mutate(newPolls, false); + }, [mutate, index, polls]); + + return ( + // To re-render on list resize, add this info to key + <div key={`${key}-${poll._id}-${polls.length}`} style={style}> + <PollCard poll={poll} setPoll={setPoll} /> + </div> + ); +}, compareProps); + + +export default RenderItem; + |