aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authoreug-vs <eug-vs@keemail.me>2020-08-14 19:24:00 +0300
committereug-vs <eug-vs@keemail.me>2020-08-14 19:24:17 +0300
commite4452e3e575b57031de83259bbd403faa7cdce2a (patch)
treed3e47f724def8a9397e256f4946e1aa1e43d87f4 /src/components
parentf78da28da3ee30b0c458c10c97db9ae7d2c6372d (diff)
downloadwhich-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.tsx44
-rw-r--r--src/components/PollsList/RenderItem.tsx47
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;
+