Skip to content

Instantly share code, notes, and snippets.

@christopherdro
Created October 11, 2015 21:02
Show Gist options
  • Star 40 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save christopherdro/89bc57a19ff02f061954 to your computer and use it in GitHub Desktop.
Save christopherdro/89bc57a19ff02f061954 to your computer and use it in GitHub Desktop.
/**
* @providesModule PatientList
*/
import NavigationBar from 'react-native-navbar';
import NavigationButtons from 'NavigationButtons';
import React, { ListView, Navigator, StyleSheet, Text, TextInput, TouchableHighlight, View } from 'react-native';
import { connect } from 'react-redux/native'
@connect(state => ({
patients: state.patients
}))
export default class PatientList extends React.Component {
constructor(props) {
super(props);
let dataSource = new ListView.DataSource({
sectionHeaderHasChanged: this._sectionHeaderHasChanged,
rowHasChanged: this._rowHasChanged,
});
this.state = {
dataSource: dataSource
}
}
componentDidMount() {
// let listViewScrollView = this.refs.listView.getScrollResponder();
// listViewScrollView.scrollTo(1); // Hack to get ListView to render fully
}
componentWillReceiveProps(nextProps) {
if (nextProps.patients !== this.props.patients) {
let {data, sectionIds} = this._getListViewData(nextProps.patients);
this.setState({
dataSource: this.state.dataSource.cloneWithRowsAndSections(data, sectionIds)
})
}
}
_getListViewData(patients) {
let data = {};
let sectionIds = [];
patients.map((patient) => {
let section = patient.lastName.charAt(0);
if (sectionIds.indexOf(section) === -1) {
sectionIds.push(section);
data[section] = [];
}
data[section].push(patient);
});
return {data, sectionIds};
}
_sectionHeaderHasChanged(oldSection, newSection) {
return oldSection !== newSection;
}
_rowHasChanged(oldRow, newRow) {
return oldRow !== newRow;
}
_onPressButton(rowID, rowData) {
this.props.navigator.push({
id: 'patient-notes',
data: rowData,
sceneConfig: Navigator.SceneConfigs.FloatFromRight,
navigationBar: (
<NavigationBar
title={`${rowData.lastName}, ${rowData.firstName.charAt(0)}.`}
buttonsColor="#48D1CC"
customNext={<NavigationButtons.AddNote patient={rowData} NavigationEmitter={this.props.NavigationEmitter}/>}
style={{flex: 1}}
/>
)
});
}
_renderRow(rowData, sectionID, rowID) {
return (
<TouchableHighlight underlayColor={'#ccc'} onPress={() => this._onPressButton(rowID, rowData)}>
<View>
<View style={styles.row}>
<Text style={[styles.text, styles.boldText]}>{rowData.lastName}, </Text>
<Text style={styles.text}>{rowData.firstName}</Text>
</View>
</View>
</TouchableHighlight>
);
}
_renderSectionHeader(data, sectionId) {
var text;
return (
<View style={styles.sectionHeader}>
<Text style={styles.sectionHeaderText}>{sectionId}</Text>
</View>
);
}
_renderSeparator(sectionID, rowID, adjacentRowHighlighted) {
var style = styles.rowSeparator;
if (adjacentRowHighlighted) {
style = [style, styles.rowSeparatorHide];
}
return (
<View key={"SEP_" + sectionID + "_" + rowID} style={style}/>
);
}
render() {
return (
<ListView
ref="listView"
automaticallyAdjustContentInsets={false}
dataSource={this.state.dataSource}
renderRow={::this._renderRow}
renderSectionHeader={this._renderSectionHeader}
renderSeparator={this._renderSeparator}
/>
);
}
}
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
padding: 15,
},
rowSeparator: {
backgroundColor: 'rgba(0, 0, 0, 0.1)',
height: 1,
marginHorizontal: 10,
},
rowSeparatorHide: {
opacity: 0.0,
},
sectionHeader: {
backgroundColor: '#48D1CC'
},
sectionHeaderText: {
fontFamily: 'AvenirNext-Medium',
fontSize: 16,
color: 'white',
paddingLeft: 10
},
thumb: {
width: 64,
height: 64,
},
text: {
fontFamily: 'AvenirNext-Medium',
fontSize: 16
},
boldText: {
fontFamily: 'AvenirNext-Bold',
},
});
// PatientList.propTypes = {
// // onAddClick: PropTypes.func.isRequired
// };
@ofirgeller
Copy link

@lodev09

If you are using redux you should not mutate the state. You concerens might be that:

  1. state changes and we don't update the view
  2. data doesn't change but we think it has so we render the view again and take a pref hit.

Since we know the original array will never change (unless you are abusing redux) we can do a shallow equality check. if the reference is the same the data must be the same.

Now if for some reason a reducer has created a brand new array that has the exact same items (why would you do that?) you will do some more work. but not a lot since _rowHasChanged is going to return false for all items, meaning that when react goes over the list and renders each item it can see the specific item is the same and avoid rendering it again.

If someone actually created a whole new list with whole new items that are copies of the original then yes, you will do extra work. but why would anyone do that?

@tquiroga
Copy link

Thank you for that gist! Very useful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment