* Right now this just flattens everything into one list and uses VirtualizedList under the * hood. The only operation that might not scale well is concatting the data arrays of all the * sections when new props are received, which should be plenty fast for up to ~10,000 items.
| 129 | * sections when new props are received, which should be plenty fast for up to ~10,000 items. |
| 130 | */ |
| 131 | class VirtualizedSectionList<SectionT: SectionBase> |
| 132 | extends React.PureComponent<DefaultProps, Props<SectionT>, State> |
| 133 | { |
| 134 | props: Props<SectionT>; |
| 135 | |
| 136 | state: State; |
| 137 | |
| 138 | static defaultProps: DefaultProps = { |
| 139 | ...VirtualizedList.defaultProps, |
| 140 | data: [], |
| 141 | }; |
| 142 | |
| 143 | scrollToLocation(params: { |
| 144 | animated?: ?boolean, itemIndex: number, sectionIndex: number, viewPosition?: number |
| 145 | }) { |
| 146 | let index = params.itemIndex + 1; |
| 147 | for (let ii = 0; ii < params.sectionIndex; ii++) { |
| 148 | index += this.props.sections[ii].data.length + 1; |
| 149 | } |
| 150 | const toIndexParams = { |
| 151 | ...params, |
| 152 | index, |
| 153 | }; |
| 154 | this._listRef.scrollToIndex(toIndexParams); |
| 155 | } |
| 156 | |
| 157 | getListRef(): VirtualizedList { |
| 158 | return this._listRef; |
| 159 | } |
| 160 | |
| 161 | _keyExtractor = (item: Item, index: number) => { |
| 162 | const info = this._subExtractor(index); |
| 163 | return (info && info.key) || String(index); |
| 164 | }; |
| 165 | |
| 166 | _subExtractor( |
| 167 | index: number, |
| 168 | ): ?{ |
| 169 | section: SectionT, |
| 170 | key: string, // Key of the section or combined key for section + item |
| 171 | index: ?number, // Relative index within the section |
| 172 | leadingItem?: ?Item, |
| 173 | leadingSection?: ?SectionT, |
| 174 | trailingItem?: ?Item, |
| 175 | trailingSection?: ?SectionT, |
| 176 | } { |
| 177 | let itemIndex = index; |
| 178 | const defaultKeyExtractor = this.props.keyExtractor; |
| 179 | for (let ii = 0; ii < this.props.sections.length; ii++) { |
| 180 | const section = this.props.sections[ii]; |
| 181 | const key = section.key || String(ii); |
| 182 | itemIndex -= 1; // The section itself is an item |
| 183 | if (itemIndex >= section.data.length) { |
| 184 | itemIndex -= section.data.length; |
| 185 | } else if (itemIndex === -1) { |
| 186 | return {section, key, index: null, trailingSection: this.props.sections[ii + 1]}; |
| 187 | } else { |
| 188 | const keyExtractor = section.keyExtractor || defaultKeyExtractor; |
nothing calls this directly
no test coverage detected