From 6283878e17a74672371f769c45ad7b27ea74f8e3 Mon Sep 17 00:00:00 2001 From: Spencer Ahrens Date: Thu, 16 Feb 2017 18:59:59 -0800 Subject: [PATCH] API update and bug fixes Reviewed By: bvaughn, yungsters Differential Revision: D4563798 fbshipit-source-id: 0591cef7c854b525d77e526af783284d9696cb48 --- Examples/UIExplorer/js/ListExampleShared.js | 10 ++--- Examples/UIExplorer/js/SectionListExample.js | 24 ++++++----- Libraries/Experimental/SectionList.js | 40 +++++++++++-------- .../Experimental/VirtualizedSectionList.js | 20 ++++++---- 4 files changed, 56 insertions(+), 38 deletions(-) diff --git a/Examples/UIExplorer/js/ListExampleShared.js b/Examples/UIExplorer/js/ListExampleShared.js index 720b2f434e9b3e..82bd6227e7afac 100644 --- a/Examples/UIExplorer/js/ListExampleShared.js +++ b/Examples/UIExplorer/js/ListExampleShared.js @@ -35,7 +35,7 @@ const { View, } = ReactNative; -type Item = {title: string, text: string, key: number, pressed: boolean}; +type Item = {title: string, text: string, key: number, pressed: boolean, noImage?: ?boolean}; function genItemData(count: number): Array { const dataBlob = []; @@ -73,7 +73,7 @@ class ItemComponent extends React.PureComponent { style={horizontal ? styles.horizItem : styles.item}> - + {!item.noImage && } @@ -108,7 +108,7 @@ class FooterComponent extends React.PureComponent { - FOOTER + LIST FOOTER ); @@ -120,7 +120,7 @@ class HeaderComponent extends React.PureComponent { return ( - HEADER + LIST HEADER @@ -164,7 +164,7 @@ function hashCode(str: string): number { return hash; } -const HEADER = {height: 30, width: 80}; +const HEADER = {height: 30, width: 100}; const SEPARATOR_HEIGHT = StyleSheet.hairlineWidth; function getItemLayout(data: any, index: number, horizontal?: boolean) { diff --git a/Examples/UIExplorer/js/SectionListExample.js b/Examples/UIExplorer/js/SectionListExample.js index 0b05ad6a79c39c..60135062d313ef 100644 --- a/Examples/UIExplorer/js/SectionListExample.js +++ b/Examples/UIExplorer/js/SectionListExample.js @@ -36,6 +36,7 @@ const UIExplorerPage = require('./UIExplorerPage'); const infoLog = require('infoLog'); const { + HeaderComponent, FooterComponent, ItemComponent, PlainInput, @@ -53,10 +54,10 @@ const SectionHeaderComponent = ({section}) => ( ); -const SectionSeparatorComponent = () => ( +const CustomSeparatorComponent = ({text}) => ( - SECTION SEPARATOR + {text} ); @@ -94,20 +95,25 @@ class SectionListExample extends React.PureComponent { } + ItemSeparatorComponent={() => } enableVirtualization={this.state.virtualized} onRefresh={() => alert('onRefresh: nothing to refresh :P')} onViewableItemsChanged={this._onViewableItemsChanged} refreshing={false} sections={[ {ItemComponent: StackedItemComponent, key: 's1', data: [ - {title: 'Item In Header Section', text: 's1', key: '0'} + {title: 'Item In Header Section', text: 'Section s1', key: '0'}, ]}, - {key: 's2', data: filteredData}, + {key: 's2', data: [ + {noImage: true, title: 'First item', text: 'Section s2', key: '0'}, + {noImage: true, title: 'Second item', text: 'Section s2', key: '1'}, + ]}, + {key: 'Filtered Items', data: filteredData}, ]} viewablePercentThreshold={100} /> @@ -143,11 +149,11 @@ const styles = StyleSheet.create({ searchRow: { paddingHorizontal: 10, }, - sectionSeparatorText: { + separatorText: { color: 'gray', alignSelf: 'center', padding: 4, - fontWeight: 'bold', + fontSize: 9, }, }); diff --git a/Libraries/Experimental/SectionList.js b/Libraries/Experimental/SectionList.js index c7dfca6de574ba..ad946e062da6ac 100644 --- a/Libraries/Experimental/SectionList.js +++ b/Libraries/Experimental/SectionList.js @@ -66,27 +66,30 @@ type RequiredProps> = { }; type OptionalProps> = { - /** - * Rendered after the last item in the last section. - */ - FooterComponent?: ?ReactClass<*>, /** * Default renderer for every item in every section. */ ItemComponent: ReactClass<{item: Item, index: number}>, /** - * Rendered at the top of each section. In the future, a sticky option will be added. + * Rendered in between adjacent Items within each section. */ - SectionHeaderComponent?: ?ReactClass<{section: SectionT}>, + ItemSeparatorComponent?: ?ReactClass<*>, /** - * Rendered at the bottom of every Section, except the very last one, in place of the normal - * SeparatorComponent. + * Rendered at the very beginning of the list. */ - SectionSeparatorComponent?: ?ReactClass<*>, + ListHeaderComponent?: ?ReactClass<*>, /** - * Rendered at the bottom of every Item except the very last one in the last section. + * Rendered at the very end of the list. */ - SeparatorComponent?: ?ReactClass<*>, + ListFooterComponent?: ?ReactClass<*>, + /** + * Rendered at the top of each section. Sticky headers are not yet supported. + */ + SectionHeaderComponent?: ?ReactClass<{section: SectionT}>, + /** + * Rendered in between each section. + */ + SectionSeparatorComponent?: ?ReactClass<*>, /** * Warning: Virtualization can drastically improve memory consumption for long lists, but trashes * the state of items when they scroll out of the render window, so make sure all relavent data is @@ -143,11 +146,16 @@ class SectionList> static defaultProps: DefaultProps = VirtualizedSectionList.defaultProps; render() { - if (this.props.legacyImplementation) { - return ; - } else { - return ; - } + const {ListFooterComponent, ListHeaderComponent, ItemSeparatorComponent} = this.props; + const List = this.props.legacyImplementation ? MetroListView : VirtualizedSectionList; + return ( + + ); } } diff --git a/Libraries/Experimental/VirtualizedSectionList.js b/Libraries/Experimental/VirtualizedSectionList.js index b669aeafb32a58..88d9c3ac46dc92 100644 --- a/Libraries/Experimental/VirtualizedSectionList.js +++ b/Libraries/Experimental/VirtualizedSectionList.js @@ -163,14 +163,18 @@ class VirtualizedSectionList const defaultKeyExtractor = this.props.keyExtractor; for (let ii = 0; ii < this.props.sections.length; ii++) { const section = this.props.sections[ii]; - const keyExtractor = section.keyExtractor || defaultKeyExtractor; - const key = keyExtractor(section, ii); + const key = section.key; + warning( + key != null, + 'VirtualizedSectionList: A `section` you supplied is missing the `key` property.' + ); itemIndex -= 1; // The section itself is an item if (itemIndex >= section.data.length) { itemIndex -= section.data.length; } else if (itemIndex === -1) { return {section, key, index: null}; } else { + const keyExtractor = section.keyExtractor || defaultKeyExtractor; return { section, key: key + ':' + keyExtractor(section.data[itemIndex], itemIndex), @@ -216,7 +220,8 @@ class VirtualizedSectionList if (!info) { return null; } else if (info.index == null) { - return ; + const {SectionHeaderComponent} = this.props; + return SectionHeaderComponent ? : null; } else { const ItemComponent = info.section.ItemComponent || this.props.ItemComponent; const SeparatorComponent = this._getSeparatorComponent(index, info); @@ -236,13 +241,12 @@ class VirtualizedSectionList } const SeparatorComponent = info.section.SeparatorComponent || this.props.SeparatorComponent; const {SectionSeparatorComponent} = this.props; - const lastItemIndex = this.state.childProps.getItemCount() - 1; - if (SectionSeparatorComponent && - info.index === info.section.data.length - 1 && - index < lastItemIndex) { + const isLastItemInList = index === this.state.childProps.getItemCount() - 1; + const isLastItemInSection = info.index === info.section.data.length - 1; + if (SectionSeparatorComponent && isLastItemInSection && !isLastItemInList) { return SectionSeparatorComponent; } - if (SeparatorComponent && index < lastItemIndex) { + if (SeparatorComponent && !isLastItemInSection && !isLastItemInList) { return SeparatorComponent; } return null;