diff --git a/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js b/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js index 1c77581facf..ff6b3fb2779 100644 --- a/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js +++ b/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js @@ -60,6 +60,7 @@ const Item = ({item, separators}: ListRenderItemInfo) => { }; type Props = Readonly<{ + data?: ReadonlyArray, exampleProps: Partial>, exampleTestID?: ?string, onTest?: ?() => void, @@ -95,7 +96,7 @@ const BaseFlatListExample: component( ref={ref} testID="flat_list" // $FlowFixMe[incompatible-type] - data={DATA} + data={props.data ?? DATA} keyExtractor={(item, index) => item + index} style={styles.list} // $FlowFixMe[incompatible-type] diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js b/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js index 132778d07b8..2a60d653160 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js @@ -12,33 +12,129 @@ import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; -import BaseFlatListExample from './BaseFlatListExample'; +import BaseFlatListExample, {ITEM_HEIGHT} from './BaseFlatListExample'; import * as React from 'react'; import {useRef, useState} from 'react'; +import {Button, FlatList} from 'react-native'; + +const DATA = Array.from({length: 20}, (_, index) => `Item ${index}`); +const SCROLL_TO_ITEM = DATA[18]; + +type EventCounts = { + dragEvents: number, + onEndReached: number, + onMomentumScrollEnd: number, + onStartReached: number, +}; export component FlatList_onEndReached() { - const [output, setOutput] = useState(''); - const exampleProps = { - onEndReached: (info: {distanceFromEnd: number, ...}) => - setOutput('onEndReached'), - onEndReachedThreshold: 0, + const [output, setOutput] = useState('ready'); + const listRef = useRef>(null); + const actionRef = useRef<'end' | 'start'>('end'); + const attemptsRef = useRef(0); + const eventCountsRef = useRef({ + dragEvents: 0, + onEndReached: 0, + onMomentumScrollEnd: 0, + onStartReached: 0, + }); + const recordEventsRef = useRef(false); + const momentumEndedRef = useRef(false); + + const report = () => { + const {dragEvents, onEndReached, onMomentumScrollEnd, onStartReached} = + eventCountsRef.current; + setOutput( + `${actionRef.current}: attempts=${attemptsRef.current}, ` + + `onEndReached=${onEndReached}, onStartReached=${onStartReached}, ` + + `onMomentumScrollEnd=${onMomentumScrollEnd}, dragEvents=${dragEvents}`, + ); + }; + + const onEndReached = () => { + if (recordEventsRef.current) { + eventCountsRef.current.onEndReached++; + if (momentumEndedRef.current) { + report(); + } + } + }; + + const onStartReached = () => { + if (recordEventsRef.current) { + eventCountsRef.current.onStartReached++; + if (momentumEndedRef.current) { + report(); + } + } }; - const ref = useRef(null); - const onTest = () => { - const scrollResponder = ref?.current?.getScrollResponder(); - if (scrollResponder != null) { - scrollResponder.scrollToEnd(); + const onMomentumScrollEnd = () => { + if (recordEventsRef.current) { + eventCountsRef.current.onMomentumScrollEnd++; + momentumEndedRef.current = true; + report(); } }; + const onDragEvent = () => { + if (recordEventsRef.current) { + eventCountsRef.current.dragEvents++; + } + }; + + const scrollToEnd = () => { + recordEventsRef.current = true; + momentumEndedRef.current = false; + actionRef.current = 'end'; + attemptsRef.current++; + setOutput('running'); + listRef.current?.scrollToItem({ + animated: true, + item: SCROLL_TO_ITEM, + viewOffset: -ITEM_HEIGHT, + }); + }; + + const scrollToStart = () => { + momentumEndedRef.current = false; + actionRef.current = 'start'; + attemptsRef.current++; + setOutput('running'); + listRef.current?.scrollToOffset({animated: true, offset: 0}); + }; + + const exampleProps = { + initialNumToRender: 19, + onEndReached, + onEndReachedThreshold: 0.2, + onMomentumScrollEnd, + onScrollBeginDrag: onDragEvent, + onScrollEndDrag: onDragEvent, + onStartReached, + onStartReachedThreshold: 0.1, + windowSize: 2, + }; + return ( + onTest={scrollToEnd} + testLabel="Scroll to item"> +