mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-01-12 22:51:09 +08:00
[change] Update VirtualizedSectionList implementation
Mirror contents of React Native 0.57.5 Ref #1172
This commit is contained in:
@@ -1638,7 +1638,6 @@ class CellRenderer extends React.Component<
|
||||
getItemLayout?: ?Function,
|
||||
renderItem: renderItemType,
|
||||
},
|
||||
prevCellKey: ?string
|
||||
prevCellKey: ?string,
|
||||
},
|
||||
$FlowFixMeState,
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
* @noflow
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import View from '../../../exports/View';
|
||||
import VirtualizedList, { type Props as VirtualizedListProps } from '../VirtualizedList';
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
|
||||
import type { ViewToken } from '../ViewabilityHelper';
|
||||
|
||||
type Item = any;
|
||||
@@ -33,12 +35,12 @@ type SectionBase = {
|
||||
updateProps: (select: 'leading' | 'trailing', newProps: Object) => void,
|
||||
},
|
||||
}) => ?React.Element<any>,
|
||||
ItemSeparatorComponent?: ?React.ComponentType<*>,
|
||||
ItemSeparatorComponent?: ?React.ComponentType<any>,
|
||||
keyExtractor?: (item: SectionItem, index: ?number) => string,
|
||||
|
||||
// TODO: support more optional/override props
|
||||
// FooterComponent?: ?ReactClass<*>,
|
||||
// HeaderComponent?: ?ReactClass<*>,
|
||||
// FooterComponent?: ?ReactClass<any>,
|
||||
// HeaderComponent?: ?ReactClass<any>,
|
||||
// onViewableItemsChanged?: ({viewableItems: Array<ViewToken>, changed: Array<ViewToken>}) => void,
|
||||
};
|
||||
|
||||
@@ -50,11 +52,11 @@ type OptionalProps<SectionT: SectionBase> = {
|
||||
/**
|
||||
* Rendered after the last item in the last section.
|
||||
*/
|
||||
ListFooterComponent?: ?(React.ComponentType<*> | React.Element<any>),
|
||||
ListFooterComponent?: ?(React.ComponentType<any> | React.Element<any>),
|
||||
/**
|
||||
* Rendered at the very beginning of the list.
|
||||
*/
|
||||
ListHeaderComponent?: ?(React.ComponentType<*> | React.Element<any>),
|
||||
ListHeaderComponent?: ?(React.ComponentType<any> | React.Element<any>),
|
||||
/**
|
||||
* Default renderer for every item in every section.
|
||||
*/
|
||||
@@ -80,11 +82,11 @@ type OptionalProps<SectionT: SectionBase> = {
|
||||
* Rendered at the bottom of every Section, except the very last one, in place of the normal
|
||||
* ItemSeparatorComponent.
|
||||
*/
|
||||
SectionSeparatorComponent?: ?React.ComponentType<*>,
|
||||
SectionSeparatorComponent?: ?React.ComponentType<any>,
|
||||
/**
|
||||
* Rendered at the bottom of every Item except the very last one in the last section.
|
||||
*/
|
||||
ItemSeparatorComponent?: ?React.ComponentType<*>,
|
||||
ItemSeparatorComponent?: ?React.ComponentType<any>,
|
||||
/**
|
||||
* 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
|
||||
@@ -97,7 +99,7 @@ type OptionalProps<SectionT: SectionBase> = {
|
||||
* If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make
|
||||
* sure to also set the `refreshing` prop correctly.
|
||||
*/
|
||||
onRefresh?: ?Function,
|
||||
onRefresh?: ?() => void,
|
||||
/**
|
||||
* Called when the viewability of rows changes, as defined by the
|
||||
* `viewabilityConfig` prop.
|
||||
@@ -130,10 +132,6 @@ class VirtualizedSectionList<SectionT: SectionBase> extends React.PureComponent<
|
||||
Props<SectionT>,
|
||||
State,
|
||||
> {
|
||||
props: Props<SectionT>;
|
||||
|
||||
state: State;
|
||||
|
||||
static defaultProps: DefaultProps = {
|
||||
...VirtualizedList.defaultProps,
|
||||
data: [],
|
||||
@@ -160,6 +158,48 @@ class VirtualizedSectionList<SectionT: SectionBase> extends React.PureComponent<
|
||||
return this._listRef;
|
||||
}
|
||||
|
||||
constructor(props: Props<SectionT>, context: Object) {
|
||||
super(props, context);
|
||||
this.state = this._computeState(props);
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps: Props<SectionT>) {
|
||||
this.setState(this._computeState(nextProps));
|
||||
}
|
||||
|
||||
_computeState(props: Props<SectionT>): State {
|
||||
const offset = props.ListHeaderComponent ? 1 : 0;
|
||||
const stickyHeaderIndices = [];
|
||||
const itemCount = props.sections.reduce((v, section) => {
|
||||
stickyHeaderIndices.push(v + offset);
|
||||
return v + section.data.length + 2; // Add two for the section header and footer.
|
||||
}, 0);
|
||||
|
||||
return {
|
||||
childProps: {
|
||||
...props,
|
||||
renderItem: this._renderItem,
|
||||
ItemSeparatorComponent: undefined, // Rendered with renderItem
|
||||
data: props.sections,
|
||||
getItemCount: () => itemCount,
|
||||
getItem,
|
||||
keyExtractor: this._keyExtractor,
|
||||
onViewableItemsChanged: props.onViewableItemsChanged
|
||||
? this._onViewableItemsChanged
|
||||
: undefined,
|
||||
stickyHeaderIndices: props.stickySectionHeadersEnabled
|
||||
? stickyHeaderIndices
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<VirtualizedList {...this.state.childProps} ref={this._captureRef} />
|
||||
);
|
||||
}
|
||||
|
||||
_keyExtractor = (item: Item, index: number) => {
|
||||
const info = this._subExtractor(index);
|
||||
return (info && info.key) || String(index);
|
||||
@@ -303,7 +343,7 @@ class VirtualizedSectionList<SectionT: SectionBase> extends React.PureComponent<
|
||||
_getSeparatorComponent(
|
||||
index: number,
|
||||
info?: ?Object,
|
||||
): ?React.ComponentType<*> {
|
||||
): ?React.ComponentType<any> {
|
||||
info = info || this._subExtractor(index);
|
||||
if (!info) {
|
||||
return null;
|
||||
@@ -322,48 +362,6 @@ class VirtualizedSectionList<SectionT: SectionBase> extends React.PureComponent<
|
||||
return null;
|
||||
}
|
||||
|
||||
_computeState(props: Props<SectionT>): State {
|
||||
const offset = props.ListHeaderComponent ? 1 : 0;
|
||||
const stickyHeaderIndices = [];
|
||||
const itemCount = props.sections.reduce((v, section) => {
|
||||
stickyHeaderIndices.push(v + offset);
|
||||
return v + section.data.length + 2; // Add two for the section header and footer.
|
||||
}, 0);
|
||||
|
||||
return {
|
||||
childProps: {
|
||||
...props,
|
||||
renderItem: this._renderItem,
|
||||
ItemSeparatorComponent: undefined, // Rendered with renderItem
|
||||
data: props.sections,
|
||||
getItemCount: () => itemCount,
|
||||
getItem,
|
||||
keyExtractor: this._keyExtractor,
|
||||
onViewableItemsChanged: props.onViewableItemsChanged
|
||||
? this._onViewableItemsChanged
|
||||
: undefined,
|
||||
stickyHeaderIndices: props.stickySectionHeadersEnabled
|
||||
? stickyHeaderIndices
|
||||
: undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props: Props<SectionT>, context: Object) {
|
||||
super(props, context);
|
||||
this.state = this._computeState(props);
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps: Props<SectionT>) {
|
||||
this.setState(this._computeState(nextProps));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<VirtualizedList {...this.state.childProps} ref={this._captureRef} />
|
||||
);
|
||||
}
|
||||
|
||||
_cellRefs = {};
|
||||
_listRef: VirtualizedList;
|
||||
_captureRef = ref => {
|
||||
@@ -374,25 +372,40 @@ class VirtualizedSectionList<SectionT: SectionBase> extends React.PureComponent<
|
||||
};
|
||||
}
|
||||
|
||||
type ItemWithSeparatorProps = {
|
||||
LeadingSeparatorComponent: ?React.ComponentType<*>,
|
||||
SeparatorComponent: ?React.ComponentType<*>,
|
||||
type ItemWithSeparatorCommonProps = $ReadOnly<{|
|
||||
leadingItem: ?Item,
|
||||
leadingSection: ?Object,
|
||||
section: Object,
|
||||
trailingItem: ?Item,
|
||||
trailingSection: ?Object,
|
||||
|}>;
|
||||
|
||||
type ItemWithSeparatorProps = $ReadOnly<{|
|
||||
...ItemWithSeparatorCommonProps,
|
||||
LeadingSeparatorComponent: ?React.ComponentType<any>,
|
||||
SeparatorComponent: ?React.ComponentType<any>,
|
||||
cellKey: string,
|
||||
index: number,
|
||||
item: Item,
|
||||
onUpdateSeparator: (cellKey: string, newProps: Object) => void,
|
||||
prevCellKey?: ?string,
|
||||
renderItem: Function,
|
||||
section: Object,
|
||||
leadingItem: ?Item,
|
||||
leadingSection: ?Object,
|
||||
trailingItem: ?Item,
|
||||
trailingSection: ?Object,
|
||||
|}>;
|
||||
|
||||
type ItemWithSeparatorState = {
|
||||
separatorProps: $ReadOnly<{|
|
||||
highlighted: false,
|
||||
...ItemWithSeparatorCommonProps,
|
||||
|}>,
|
||||
leadingSeparatorProps: $ReadOnly<{|
|
||||
highlighted: false,
|
||||
...ItemWithSeparatorCommonProps,
|
||||
|}>,
|
||||
};
|
||||
|
||||
class ItemWithSeparator extends React.Component<
|
||||
ItemWithSeparatorProps,
|
||||
$FlowFixMeState,
|
||||
ItemWithSeparatorState,
|
||||
> {
|
||||
state = {
|
||||
separatorProps: {
|
||||
@@ -426,7 +439,7 @@ class ItemWithSeparator extends React.Component<
|
||||
},
|
||||
updateProps: (select: 'leading' | 'trailing', newProps: Object) => {
|
||||
const {LeadingSeparatorComponent, cellKey, prevCellKey} = this.props;
|
||||
if (select === 'leading' && LeadingSeparatorComponent) {
|
||||
if (select === 'leading' && LeadingSeparatorComponent != null) {
|
||||
this.setState(state => ({
|
||||
leadingSeparatorProps: {...state.leadingSeparatorProps, ...newProps},
|
||||
}));
|
||||
@@ -439,10 +452,13 @@ class ItemWithSeparator extends React.Component<
|
||||
},
|
||||
};
|
||||
|
||||
UNSAFE_componentWillReceiveProps(props: ItemWithSeparatorProps) {
|
||||
this.setState(state => ({
|
||||
static getDerivedStateFromProps(
|
||||
props: ItemWithSeparatorProps,
|
||||
prevState: ItemWithSeparatorState,
|
||||
): ?ItemWithSeparatorState {
|
||||
return {
|
||||
separatorProps: {
|
||||
...this.state.separatorProps,
|
||||
...prevState.separatorProps,
|
||||
leadingItem: props.item,
|
||||
leadingSection: props.leadingSection,
|
||||
section: props.section,
|
||||
@@ -450,14 +466,14 @@ class ItemWithSeparator extends React.Component<
|
||||
trailingSection: props.trailingSection,
|
||||
},
|
||||
leadingSeparatorProps: {
|
||||
...this.state.leadingSeparatorProps,
|
||||
...prevState.leadingSeparatorProps,
|
||||
leadingItem: props.leadingItem,
|
||||
leadingSection: props.leadingSection,
|
||||
section: props.section,
|
||||
trailingItem: props.item,
|
||||
trailingSection: props.trailingSection,
|
||||
},
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
updateSeparatorProps(newProps: Object) {
|
||||
|
||||
Reference in New Issue
Block a user