Skip to content

Commit

Permalink
Merge pull request facebook#21 from Expensify/Rory-BetterOnStartReach…
Browse files Browse the repository at this point in the history
…edExample
  • Loading branch information
roryabraham authored Aug 4, 2022
2 parents 3776d64 + 0afd352 commit 3611d2e
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 23 deletions.
48 changes: 38 additions & 10 deletions packages/rn-tester/js/components/ListExampleShared.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
const React = require('react');

const {
ActivityIndicator,
Animated,
Image,
Platform,
Expand All @@ -33,16 +34,28 @@ export type Item = {
...
};

function genItemData(count: number, start: number = 0): Array<Item> {
function genItemData(i: number): Item {
const itemHash = Math.abs(hashCode('Item ' + i));
return {
title: 'Item ' + i,
text: LOREM_IPSUM.substr(0, (itemHash % 301) + 20),
key: String(i),
pressed: false,
};
}

function genNewerItems(count: number, start: number = 0): Array<Item> {
const dataBlob = [];
for (let i = start; i < count + start; i++) {
dataBlob.push(genItemData(i));
}
return dataBlob;
}

function genOlderItems(count: number, start: number = 0): Array<Item> {
const dataBlob = [];
for (let ii = start; ii < count + start; ii++) {
const itemHash = Math.abs(hashCode('Item ' + ii));
dataBlob.push({
title: 'Item ' + ii,
text: LOREM_IPSUM.substr(0, (itemHash % 301) + 20),
key: String(ii),
pressed: false,
});
for (let i = count; i > 0; i--) {
dataBlob.push(genItemData(start - i));
}
return dataBlob;
}
Expand Down Expand Up @@ -147,6 +160,12 @@ class SeparatorComponent extends React.PureComponent<{...}> {
}
}

const LoadingComponent: React.ComponentType<{}> = React.memo(() => (
<View style={styles.loadingContainer}>
<ActivityIndicator />
</View>
));

class ItemSeparatorComponent extends React.PureComponent<$FlowFixMeProps> {
render(): React.Node {
const style = this.props.highlighted
Expand Down Expand Up @@ -352,6 +371,13 @@ const styles = StyleSheet.create({
text: {
flex: 1,
},
loadingContainer: {
alignItems: 'center',
justifyContent: 'center',
height: 100,
borderTopWidth: 1,
borderTopColor: 'rgb(200, 199, 204)',
},
});

module.exports = {
Expand All @@ -362,8 +388,10 @@ module.exports = {
ItemSeparatorComponent,
PlainInput,
SeparatorComponent,
LoadingComponent,
Spindicator,
genItemData,
genNewerItems,
genOlderItems,
getItemLayout,
pressItem,
renderSmallSwitchOption,
Expand Down
71 changes: 62 additions & 9 deletions packages/rn-tester/js/examples/FlatList/FlatList-basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,22 @@ import {
ItemSeparatorComponent,
PlainInput,
SeparatorComponent,
LoadingComponent,
Spindicator,
genItemData,
genNewerItems,
genOlderItems,
getItemLayout,
pressItem,
renderSmallSwitchOption,
} from '../../components/ListExampleShared';

import type {Item} from '../../components/ListExampleShared';

const PAGE_SIZE = 100;
const NUM_PAGES = 10;
const INITIAL_PAGE_OFFSET = Math.floor(NUM_PAGES / 2);
const LOAD_TIME = 2000;

const VIEWABILITY_CONFIG = {
minimumViewTime: 3000,
viewAreaCoveragePercentThreshold: 100,
Expand All @@ -51,6 +58,8 @@ const VIEWABILITY_CONFIG = {
type Props = $ReadOnly<{||}>;
type State = {|
data: Array<Item>,
first: number,
last: number,
debug: boolean,
horizontal: boolean,
inverted: boolean,
Expand All @@ -63,11 +72,16 @@ type State = {|
fadingEdgeLength: number,
onPressDisabled: boolean,
textSelectable: boolean,
maintainVisibleContentPosition: boolean,
previousLoading: boolean,
nextLoading: boolean,
|};

class FlatListExample extends React.PureComponent<Props, State> {
state: State = {
data: genItemData(100),
data: genNewerItems(PAGE_SIZE, PAGE_SIZE * INITIAL_PAGE_OFFSET),
first: PAGE_SIZE * INITIAL_PAGE_OFFSET,
last: PAGE_SIZE + PAGE_SIZE * INITIAL_PAGE_OFFSET,
debug: false,
horizontal: false,
inverted: false,
Expand All @@ -80,6 +94,9 @@ class FlatListExample extends React.PureComponent<Props, State> {
fadingEdgeLength: 0,
onPressDisabled: false,
textSelectable: true,
maintainVisibleContentPosition: true,
previousLoading: false,
nextLoading: false,
};

_onChangeFilterText = filterText => {
Expand Down Expand Up @@ -182,6 +199,11 @@ class FlatListExample extends React.PureComponent<Props, State> {
this.state.useFlatListItemComponent,
this._setBooleanValue('useFlatListItemComponent'),
)}
{renderSmallSwitchOption(
'Maintain content position',
this.state.maintainVisibleContentPosition,
this._setBooleanValue('maintainVisibleContentPosition'),
)}
{Platform.OS === 'android' && (
<View>
<TextInput
Expand All @@ -203,8 +225,12 @@ class FlatListExample extends React.PureComponent<Props, State> {
<Animated.FlatList
fadingEdgeLength={this.state.fadingEdgeLength}
ItemSeparatorComponent={ItemSeparatorComponent}
ListHeaderComponent={<HeaderComponent />}
ListFooterComponent={FooterComponent}
ListHeaderComponent={
this.state.previousLoading ? LoadingComponent : HeaderComponent
}
ListFooterComponent={
this.state.nextLoading ? LoadingComponent : FooterComponent
}
ListEmptyComponent={ListEmptyComponent}
data={this.state.empty ? [] : filteredData}
debug={this.state.debug}
Expand All @@ -222,6 +248,8 @@ class FlatListExample extends React.PureComponent<Props, State> {
keyboardShouldPersistTaps="always"
keyboardDismissMode="on-drag"
numColumns={1}
onStartReached={this._onStartReached}
initialScrollIndex={Math.floor(PAGE_SIZE / 2)}
onEndReached={this._onEndReached}
onRefresh={this._onRefresh}
onScroll={
Expand All @@ -232,6 +260,11 @@ class FlatListExample extends React.PureComponent<Props, State> {
refreshing={false}
contentContainerStyle={styles.list}
viewabilityConfig={VIEWABILITY_CONFIG}
maintainVisibleContentPosition={
this.state.maintainVisibleContentPosition
? {minIndexForVisible: 1}
: undefined
}
{...flatListItemRendererProps}
/>
</View>
Expand All @@ -251,13 +284,33 @@ class FlatListExample extends React.PureComponent<Props, State> {
_getItemLayout = (data: any, index: number) => {
return getItemLayout(data, index, this.state.horizontal);
};
_onStartReached = () => {
if (this.state.first <= 0 || this.state.previousLoading) {
return;
}

this.setState({previousLoading: true});
setTimeout(() => {
this.setState(state => ({
previousLoading: false,
data: genOlderItems(PAGE_SIZE, state.first).concat(state.data),
first: state.first - PAGE_SIZE,
}));
}, LOAD_TIME);
};
_onEndReached = () => {
if (this.state.data.length >= 1000) {
if (this.state.last >= PAGE_SIZE * NUM_PAGES || this.state.nextLoading) {
return;
}
this.setState(state => ({
data: state.data.concat(genItemData(100, state.data.length)),
}));

this.setState({nextLoading: true});
setTimeout(() => {
this.setState(state => ({
nextLoading: false,
data: state.data.concat(genNewerItems(PAGE_SIZE, state.last)),
last: state.last + PAGE_SIZE,
}));
}, LOAD_TIME);
};
_onPressCallback = () => {
const {onPressDisabled} = this.state;
Expand Down Expand Up @@ -315,7 +368,7 @@ class FlatListExample extends React.PureComponent<Props, State> {

_pressItem = (key: string) => {
this._listRef && this._listRef.recordInteraction();
const index = Number(key);
const index = this.state.data.findIndex(item => item.key === key);
const itemState = pressItem(this.state.data[index]);
this.setState(state => ({
...state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const {
ItemComponent,
PlainInput,
SeparatorComponent,
genItemData,
genNewerItems,
getItemLayout,
pressItem,
renderSmallSwitchOption,
Expand All @@ -46,7 +46,7 @@ class MultiColumnExample extends React.PureComponent<
numColumns: number,
virtualized: boolean,
|} = {
data: genItemData(1000),
data: genNewerItems(1000),
filterText: '',
fixedHeight: true,
logViewable: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const {
PlainInput,
SeparatorComponent,
Spindicator,
genItemData,
genNewerItems,
pressItem,
renderSmallSwitchOption,
renderStackedItem,
Expand Down Expand Up @@ -161,7 +161,7 @@ export function SectionList_scrollable(Props: {
const [logViewable, setLogViewable] = React.useState(false);
const [debug, setDebug] = React.useState(false);
const [inverted, setInverted] = React.useState(false);
const [data, setData] = React.useState(genItemData(1000));
const [data, setData] = React.useState(genNewerItems(1000));

const filterRegex = new RegExp(String(filterText), 'i');
const filter = item =>
Expand Down

0 comments on commit 3611d2e

Please sign in to comment.