Skip to content

Commit 14e9e34

Browse files
committed
#808 Improved render/update performance of a few fundamental react controls. Switched to flatlist from listview.
1 parent 4823004 commit 14e9e34

File tree

10 files changed

+121
-123
lines changed

10 files changed

+121
-123
lines changed

packages/openchs-android/package-lock.json

Lines changed: 29 additions & 53 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openchs-android/src/action/mydashboard/MyDashboardActions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ class MyDashboardActions {
244244
const genderQuery = (path) => _.map(action.selectedGenders, (gender) => `${path} = "${gender.name}"`);
245245

246246
const customFilterService = context.get(CustomFilterService);
247-
var individualUUIDs = [];
247+
let individualUUIDs = [];
248248
const selectedCustomFilterBySubjectType = _.mapValues(action.selectedCustomFilters, selectedFilters => {
249249
const s = selectedFilters.filter(filter => filter.subjectTypeUUID === action.selectedSubjectType.uuid);
250250
return s.length === 0 ? [] : s

packages/openchs-android/src/service/IndividualService.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -422,17 +422,17 @@ class IndividualService extends BaseService {
422422
fromDate)
423423
.filtered((_.isEmpty(addressQuery) ? 'uuid != null' : `${addressQuery}`))
424424
.map((individual) => {
425-
const registrationDate = individual.registrationDate;
426-
return {
427-
individual,
428-
visitInfo: {
429-
uuid: individual.uuid,
430-
visitName: [],
431-
groupingBy: General.formatDate(registrationDate),
432-
sortingBy: registrationDate,
433-
allow: true,
434-
}
435-
};
425+
const registrationDate = individual.registrationDate;
426+
return {
427+
individual,
428+
visitInfo: {
429+
uuid: individual.uuid,
430+
visitName: [],
431+
groupingBy: General.formatDate(registrationDate),
432+
sortingBy: registrationDate,
433+
allow: true,
434+
}
435+
};
436436
})
437437
.reduce(this._uniqIndividualWithVisitName, new Map())
438438
.values()]

packages/openchs-android/src/views/common/ProgramFilter.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ class ProgramFilter extends AbstractComponent {
2828
const valueLabelPairs = this.props.visits.map(({uuid, operationalProgramName, operationalEncounterTypeName, name}) => new RadioLabelValue(operationalProgramName || operationalEncounterTypeName || name, uuid, false));
2929
return (
3030
<RadioGroup
31-
multiSelect={this.props.multiSelect}
32-
style={{
33-
marginTop: Styles.VerticalSpacingBetweenInGroupFormElements,
34-
marginBottom: Styles.VerticalSpacingBetweenInGroupFormElements
35-
}}
36-
borderStyle={{borderWidth: 0}}
37-
inPairs={true}
38-
onPress={({label, value}) => this.props.onToggle(label, value)}
39-
selectionFn={(value) => this.props.selectionFn(value)}
40-
labelKey={this.props.name}
41-
mandatory={false}
31+
multiSelect={this.props.multiSelect}
32+
style={{
33+
marginTop: Styles.VerticalSpacingBetweenInGroupFormElements,
34+
marginBottom: Styles.VerticalSpacingBetweenInGroupFormElements
35+
}}
36+
borderStyle={{borderWidth: 0}}
37+
inPairs={true}
38+
onPress={({label, value}) => this.props.onToggle(label, value)}
39+
selectionFn={(value) => this.props.selectionFn(value)}
40+
labelKey={this.props.name}
41+
mandatory={false}
4242
labelValuePairs={valueLabelPairs}/>
4343
);
4444
}

packages/openchs-android/src/views/filter/FiltersView.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from "react";
2-
import {Dimensions, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
2+
import {Dimensions, StyleSheet, FlatList, Text, TouchableOpacity, View} from 'react-native';
33
import AbstractComponent from "../../framework/view/AbstractComponent";
44
import Distances from '../primitives/Distances'
55
import SingleSelectFilter from './SingleSelectFilter';

packages/openchs-android/src/views/form/ValidationErrorMessage.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ class ValidationErrorMessage extends AbstractComponent {
1515
super(props, context);
1616
}
1717

18+
shouldComponentUpdate(nextProps, nextState, nextContext) {
19+
return this.props.validationResult !== nextProps.validationResult;
20+
}
21+
1822
render() {
1923
return _.isNil(this.props.validationResult) || this.props.validationResult.success ? <View/> : <Text style={{color: Colors.ValidationError, flex: 0.3}}>{this.I18n.t(this.props.validationResult.messageKey, this.props.validationResult.extra)}</Text>;
2024
}

packages/openchs-android/src/views/individual/IndividualSearchResultsView.js

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,44 @@
11
import AbstractComponent from "../../framework/view/AbstractComponent";
2-
import {Text, TouchableNativeFeedback, View} from "react-native";
3-
import ListView from "deprecated-react-native-listview";
2+
import {FlatList, TouchableNativeFeedback, View} from "react-native";
43
import PropTypes from 'prop-types';
5-
import React from "react";
4+
import React, {Component} from "react";
65
import Path from "../../framework/routing/Path";
7-
import GlobalStyles from "../primitives/GlobalStyles";
86
import AppHeader from "../common/AppHeader";
97
import Colors from "../primitives/Colors";
108
import General from "../../utility/General";
11-
import CHSContainer from "../common/CHSContainer";
12-
import Styles from "../primitives/Styles";
139
import SearchResultsHeader from "./SearchResultsHeader";
1410
import IndividualDetailsCard from "../common/IndividualDetailsCard";
1511
import {IndividualSearchActionNames as Actions} from "../../action/individual/IndividualSearchActions";
16-
import {Individual} from "openchs-models";
17-
import ListViewHelper from "../../utility/ListViewHelper";
12+
import {getUnderlyingRealmCollection, Individual} from "openchs-models";
1813
import ZeroResults from "../common/ZeroResults";
1914

15+
class IndividualSearchResultRow extends Component {
16+
static propTypes = {
17+
item: PropTypes.any.isRequired,
18+
onResultRowPress: PropTypes.func.isRequired
19+
}
20+
21+
constructor(props, context) {
22+
super(props, context);
23+
}
24+
25+
shouldComponentUpdate() {
26+
return false;
27+
}
28+
29+
render() {
30+
const {item, onResultRowPress} = this.props;
31+
const individual = new Individual(item);
32+
General.logDebug("IndividualSearchResultRow", `${individual.name}`);
33+
return <TouchableNativeFeedback key={individual.uuid} onPress={() => onResultRowPress(individual)}
34+
background={TouchableNativeFeedback.SelectableBackground()}>
35+
<View>
36+
<IndividualDetailsCard individual={individual}/>
37+
</View>
38+
</TouchableNativeFeedback>;
39+
}
40+
}
41+
2042
@Path('/individualSearchResults')
2143
class IndividualSearchResultsView extends AbstractComponent {
2244
static propTypes = {
@@ -39,31 +61,23 @@ class IndividualSearchResultsView extends AbstractComponent {
3961
super.UNSAFE_componentWillMount();
4062
}
4163

42-
renderRow(item, onResultRowPress) {
43-
return <TouchableNativeFeedback onPress={() => onResultRowPress(new Individual(item))}
44-
background={TouchableNativeFeedback.SelectableBackground()}>
45-
<View>
46-
<IndividualDetailsCard individual={new Individual(item)}/>
47-
</View>
48-
</TouchableNativeFeedback>
49-
}
50-
5164
render() {
5265
General.logDebug(this.viewName(), 'render');
53-
const dataSource = ListViewHelper.getDataSource(this.props.searchResults);
5466
const title = this.props.headerTitle || "searchResults";
67+
const searchResultsCollection = getUnderlyingRealmCollection(this.props.searchResults);
5568

5669
return (
57-
<CHSContainer theme={{iconFamily: 'MaterialIcons'}} style={{backgroundColor: Colors.GreyContentBackground}}>
70+
<View style={{backgroundColor: Colors.GreyContentBackground}}>
5871
<AppHeader title={this.I18n.t(title)}/>
5972
<SearchResultsHeader totalCount={this.props.totalSearchResultsCount}
6073
displayedCount={this.props.searchResults.length}/>
61-
<ListView enableEmptySections={true}
62-
dataSource={dataSource}
63-
style={{marginBottom: 16}}
64-
renderRow={(item) => this.renderRow(item, this.onResultRowPress.bind(this))}/>
74+
<FlatList
75+
data={searchResultsCollection}
76+
keyExtractor={(item) => item.uuid}
77+
renderItem={({item}) => <IndividualSearchResultRow item={item} onResultRowPress={this.onResultRowPress.bind(this)}/>}
78+
/>
6579
<ZeroResults count={this.props.searchResults.length}/>
66-
</CHSContainer>
80+
</View>
6781
);
6882
}
6983

0 commit comments

Comments
 (0)