Skip to content

Commit a5a6ae2

Browse files
authored
Improve performance agenda list (#2004)
* reduce load time on change day from around 1000 ms to 230 ms * reduce load time on change day from around 1000 ms to 230 ms * reduce load time on change day from around 1000 ms to 330 ms * fix PR comments
1 parent 9b3bbcd commit a5a6ae2

File tree

2 files changed

+42
-22
lines changed

2 files changed

+42
-22
lines changed

example/src/mocks/AgendaItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const AgendaItem = (props: ItemProps) => {
4141
);
4242
};
4343

44-
export default AgendaItem;
44+
export default React.memo(AgendaItem);
4545

4646

4747
const styles = StyleSheet.create({

src/expandableCalendar/agendaList.tsx

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import map from 'lodash/map';
55
import isFunction from 'lodash/isFunction';
66
import isUndefined from 'lodash/isUndefined';
77
import debounce from 'lodash/debounce';
8+
import isEqual from 'lodash/isEqual';
9+
810

911
import XDate from 'xdate';
1012

11-
import React, {useCallback, useContext, useEffect, useRef} from 'react';
13+
import React, {useCallback, useContext, useEffect, useMemo, useRef} from 'react';
1214
import {
1315
Text,
1416
SectionList,
@@ -19,7 +21,8 @@ import {
1921
NativeSyntheticEvent,
2022
NativeScrollEvent,
2123
LayoutChangeEvent,
22-
ViewToken
24+
ViewToken,
25+
TextProps
2326
} from 'react-native';
2427

2528
import {isToday, isGTE, sameDate} from '../dateutils';
@@ -67,23 +70,23 @@ export interface AgendaListProps extends SectionListProps<any, DefaultSectionT>
6770
*/
6871
const AgendaList = (props: AgendaListProps) => {
6972
const {
70-
theme,
71-
sections,
72-
scrollToNextEvent,
73-
viewOffset = 0,
74-
avoidDateUpdates,
75-
onScroll,
76-
onMomentumScrollBegin,
73+
theme,
74+
sections,
75+
scrollToNextEvent,
76+
viewOffset = 0,
77+
avoidDateUpdates,
78+
onScroll,
79+
onMomentumScrollBegin,
7780
onMomentumScrollEnd,
7881
onScrollToIndexFailed,
7982
renderSectionHeader,
8083
sectionStyle,
8184
keyExtractor,
82-
dayFormatter,
83-
dayFormat = 'dddd, MMM d',
84-
useMoment,
85+
dayFormatter,
86+
dayFormat = 'dddd, MMM d',
87+
useMoment,
8588
markToday = true,
86-
onViewableItemsChanged
89+
onViewableItemsChanged,
8790
} = props;
8891
const {date, updateSource, setDate, setDisabled} = useContext(Context);
8992
const style = useRef(styleConstructor(theme));
@@ -135,7 +138,7 @@ const AgendaList = (props: AgendaListProps) => {
135138
return i;
136139
};
137140

138-
const getSectionTitle = (title: string) => {
141+
const getSectionTitle = useCallback((title: string) => {
139142
if (!title) return;
140143

141144
let sectionTitle = title;
@@ -158,7 +161,7 @@ const AgendaList = (props: AgendaListProps) => {
158161
}
159162

160163
return sectionTitle;
161-
};
164+
}, []);
162165

163166
const scrollToSection = useCallback(debounce((d) => {
164167
const sectionIndex = scrollToNextEvent ? getNextSectionIndex(d) : getSectionIndex(d);
@@ -212,6 +215,8 @@ const AgendaList = (props: AgendaListProps) => {
212215
onMomentumScrollEnd?.(event);
213216
}, [onMomentumScrollEnd, setDisabled]);
214217

218+
const headerTextStyle = useMemo(() => [style.current.sectionText, sectionStyle], [sectionStyle]);
219+
215220
const _onScrollToIndexFailed = useCallback((info: {index: number; highestMeasuredFrameIndex: number; averageItemLength: number}) => {
216221
if (onScrollToIndexFailed) {
217222
onScrollToIndexFailed(info);
@@ -231,12 +236,9 @@ const AgendaList = (props: AgendaListProps) => {
231236
return renderSectionHeader(title);
232237
}
233238

234-
return (
235-
<Text allowFontScaling={false} style={[style.current.sectionText, sectionStyle]} onLayout={onHeaderLayout}>
236-
{getSectionTitle(title)}
237-
</Text>
238-
);
239-
}, []);
239+
const headerTitle = getSectionTitle(title);
240+
return <AgendaSectionHeader title={headerTitle} style={headerTextStyle} onLayout={onHeaderLayout}/>;
241+
}, [headerTextStyle]);
240242

241243
const _keyExtractor = useCallback((item: any, index: number) => {
242244
return isFunction(keyExtractor) ? keyExtractor(item, index) : String(index);
@@ -264,6 +266,24 @@ const AgendaList = (props: AgendaListProps) => {
264266
// }
265267
};
266268

269+
interface AgendaSectionHeaderProps {
270+
title?: string;
271+
onLayout: TextProps['onLayout'];
272+
style: TextProps['style'];
273+
}
274+
275+
function areTextPropsEqual(prev: AgendaSectionHeaderProps, next: AgendaSectionHeaderProps): boolean {
276+
return isEqual(prev.style, next.style) && prev.title === next.title;
277+
}
278+
279+
const AgendaSectionHeader = React.memo((props: AgendaSectionHeaderProps) => {
280+
return (
281+
<Text allowFontScaling={false} style={props.style} onLayout={props.onLayout}>
282+
{props.title}
283+
</Text>
284+
);
285+
}, areTextPropsEqual);
286+
267287
export default AgendaList;
268288

269289
AgendaList.displayName = 'AgendaList';

0 commit comments

Comments
 (0)