UNPKG

react-native-expandable-section-list

Version:

react-native-expandable-section-list is a expandable list what is similar to QQ's list of Tencent

130 lines (115 loc) 3.54 kB
/** * Created by dpcui on 27/05/2017. */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { View, ListView, ScrollView, LayoutAnimation, TouchableOpacity, RefreshControl, } from 'react-native'; class ExpandableList extends Component { constructor(props) { super(props); this.ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); this.listView; const map = new Map(); if (props.dataSource && props.isOpen) { props.dataSource.map((item, i) => map.set(i.toString(), true)) } if (props.openOptions) { props.openOptions.map((item) => map.set(item.toString(), true)) } this.state = { memberOpened: map } } componentWillReceiveProps(nextProps) { const map = new Map(); if (nextProps.dataSource && nextProps.isOpen) { nextProps.dataSource.map((item, i) => map.set(i.toString(), true)); } if (nextProps.openOptions) { nextProps.openOptions.map((item) => map.set(item.toString(), true)); } this.setState({memberOpened: map}); } static propTypes = { dataSource: PropTypes.array.isRequired, headerKey: PropTypes.string, memberKey: PropTypes.string, renderRow: PropTypes.func, renderSectionHeaderX: PropTypes.func, renderSectionFooterX: PropTypes.func, headerOnPress: PropTypes.func, isOpen: PropTypes.bool, openOptions: PropTypes.array, }; static defaultProps = { headerKey: 'header', memberKey: 'member', isOpen: false, }; setSectionState = (index, state) => { this.setState((s) => { const memberOpened = new Map(s.memberOpened); memberOpened.set(index.toString(), state); // toggle return {memberOpened}; }); LayoutAnimation.easeInEaseOut(); }; _onPress = (i) => { this.setState((state) => { const memberOpened = new Map(state.memberOpened); memberOpened.set(i, !memberOpened.get(i)); // toggle return { memberOpened }; }); if (this.props.headerOnPress) { this.props.headerOnPress(i, !(!!this.state.memberOpened.get(i))); } LayoutAnimation.easeInEaseOut(); }; _renderRow = (rowData, sectionId, rowId) => { // eslint-disable-line const { renderRow, renderSectionHeaderX, renderSectionFooterX, headerKey, memberKey } = this.props; let memberArr = rowData[memberKey]; if (!this.state.memberOpened.get(rowId) || !memberArr) { memberArr = []; } return ( <View> <TouchableOpacity onPress={() => this._onPress(rowId)}> { renderSectionHeaderX ? renderSectionHeaderX(rowData[headerKey], rowId, !!this.state.memberOpened.get(rowId)) : null} </TouchableOpacity> <ScrollView scrollEnabled={false}> { memberArr.map((rowItem, index) => { return ( <View key={index}> {renderRow ? renderRow(rowItem, index, rowId) : null} </View> ); }) } { memberArr.length > 0 && renderSectionFooterX ? renderSectionFooterX(rowData, sectionId) : null } </ScrollView> </View> ); } render() { const { dataSource } = this.props; return ( <ListView {...this.props} ref={instance => this.listView = instance} dataSource={this.ds.cloneWithRows(dataSource || [])} renderRow={this._renderRow} enableEmptySections={true} /> ); } } export default ExpandableList;