Skip to content

Commit

Permalink
Merge pull request #33288 from ishpaul777/typeScript/InvertedFlatList
Browse files Browse the repository at this point in the history
TS migration InvertedList #25137
  • Loading branch information
MonilBhavsar authored Dec 28, 2023
2 parents 34a7bbd + 64ed3d2 commit ca05400
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 112 deletions.
38 changes: 0 additions & 38 deletions src/components/InvertedFlatList/BaseInvertedFlatList.js

This file was deleted.

26 changes: 26 additions & 0 deletions src/components/InvertedFlatList/BaseInvertedFlatList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, {ForwardedRef, forwardRef} from 'react';
import {FlatListProps} from 'react-native';
import FlatList from '@components/FlatList';

const AUTOSCROLL_TO_TOP_THRESHOLD = 128;
const WINDOW_SIZE = 15;

function BaseInvertedFlatList<T>(props: FlatListProps<T>, ref: ForwardedRef<FlatList>) {
return (
<FlatList
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
ref={ref}
windowSize={WINDOW_SIZE}
maintainVisibleContentPosition={{
minIndexForVisible: 0,
autoscrollToTopThreshold: AUTOSCROLL_TO_TOP_THRESHOLD,
}}
inverted
/>
);
}

BaseInvertedFlatList.displayName = 'BaseInvertedFlatList';

export default forwardRef(BaseInvertedFlatList);
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import {StyleProp, View, ViewProps} from 'react-native';

const propTypes = {
/** Position index of the list item in a list view */
index: PropTypes.number.isRequired,

/** Styles that are passed to the component */
style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
};

const defaultProps = {
style: {},
type CellRendererComponentProps = ViewProps & {
index: number;
style?: StyleProp<ViewProps>;
};

function CellRendererComponent(props) {
function CellRendererComponent(props: CellRendererComponentProps) {
return (
<View
// eslint-disable-next-line react/jsx-props-no-spreading
Expand All @@ -34,8 +26,6 @@ function CellRendererComponent(props) {
);
}

CellRendererComponent.propTypes = propTypes;
CellRendererComponent.defaultProps = defaultProps;
CellRendererComponent.displayName = 'CellRendererComponent';

export default CellRendererComponent;
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, {forwardRef} from 'react';
import React, {ForwardedRef, forwardRef} from 'react';
import {FlatList, FlatListProps} from 'react-native';
import useThemeStyles from '@hooks/useThemeStyles';
import BaseInvertedFlatList from './BaseInvertedFlatList';
import CellRendererComponent from './CellRendererComponent';

const BaseInvertedFlatListWithRef = forwardRef((props, ref) => {
function BaseInvertedFlatListWithRef<T>(props: FlatListProps<T>, ref: ForwardedRef<FlatList>) {
const styles = useThemeStyles();
return (
<BaseInvertedFlatList
Expand All @@ -20,8 +21,8 @@ const BaseInvertedFlatListWithRef = forwardRef((props, ref) => {
removeClippedSubviews={false}
/>
);
});
}

BaseInvertedFlatListWithRef.displayName = 'BaseInvertedFlatListWithRef';

export default BaseInvertedFlatListWithRef;
export default forwardRef(BaseInvertedFlatListWithRef);
Original file line number Diff line number Diff line change
@@ -1,66 +1,45 @@
import PropTypes from 'prop-types';
import React, {forwardRef, useEffect, useRef} from 'react';
import {DeviceEventEmitter, FlatList} from 'react-native';
import React, {ForwardedRef, forwardRef, useEffect, useRef} from 'react';
import {DeviceEventEmitter, FlatList, FlatListProps, NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
import CONST from '@src/CONST';
import BaseInvertedFlatList from './BaseInvertedFlatList';

const propTypes = {
/** Passed via forwardRef so we can access the FlatList ref */
innerRef: PropTypes.shape({
current: PropTypes.instanceOf(FlatList),
}).isRequired,

/** Any additional styles to apply */
// eslint-disable-next-line react/forbid-prop-types
contentContainerStyle: PropTypes.any,

/** Same as for FlatList */
onScroll: PropTypes.func,
};

// This is adapted from https://codesandbox.io/s/react-native-dsyse
// It's a HACK alert since FlatList has inverted scrolling on web
function InvertedFlatList(props) {
const {innerRef, contentContainerStyle} = props;

const lastScrollEvent = useRef(null);
const scrollEndTimeout = useRef(null);
const updateInProgress = useRef(false);
const eventHandler = useRef(null);
function InvertedFlatList<T>({onScroll: onScrollProp = () => {}, contentContainerStyle, ...props}: FlatListProps<T>, ref: ForwardedRef<FlatList>) {
const lastScrollEvent = useRef<number | null>(null);
const scrollEndTimeout = useRef<NodeJS.Timeout | null>(null);
const updateInProgress = useRef<boolean>(false);

useEffect(
() => () => {
if (scrollEndTimeout.current) {
clearTimeout(scrollEndTimeout.current);
}

if (eventHandler.current) {
eventHandler.current.remove();
if (!scrollEndTimeout.current) {
return;
}
clearTimeout(scrollEndTimeout.current);
},
[innerRef],
[ref],
);

/**
* Emits when the scrolling is in progress. Also,
* invokes the onScroll callback function from props.
*
* @param {Event} event - The onScroll event from the FlatList
* @param event - The onScroll event from the FlatList
*/
const onScroll = (event) => {
props.onScroll(event);
const onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
onScrollProp(event);

if (!updateInProgress.current) {
updateInProgress.current = true;
eventHandler.current = DeviceEventEmitter.emit(CONST.EVENTS.SCROLLING, true);
DeviceEventEmitter.emit(CONST.EVENTS.SCROLLING, true);
}
};

/**
* Emits when the scrolling has ended.
*/
const onScrollEnd = () => {
eventHandler.current = DeviceEventEmitter.emit(CONST.EVENTS.SCROLLING, false);
DeviceEventEmitter.emit(CONST.EVENTS.SCROLLING, false);
updateInProgress.current = false;
};

Expand All @@ -77,9 +56,8 @@ function InvertedFlatList(props) {
* This workaround is taken from below and refactored to fit our needs:
* https://github.com/necolas/react-native-web/issues/1021#issuecomment-984151185
*
* @param {Event} event - The onScroll event from the FlatList
*/
const handleScroll = (event) => {
const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
onScroll(event);
const timestamp = Date.now();

Expand All @@ -105,28 +83,13 @@ function InvertedFlatList(props) {
<BaseInvertedFlatList
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
ref={innerRef}
ref={ref}
contentContainerStyle={contentContainerStyle}
onScroll={handleScroll}
/>
);
}

InvertedFlatList.propTypes = propTypes;
InvertedFlatList.defaultProps = {
contentContainerStyle: {},
onScroll: () => {},
};
InvertedFlatList.displayName = 'InvertedFlatList';

const InvertedFlatListWithRef = forwardRef((props, ref) => (
<InvertedFlatList
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
innerRef={ref}
/>
));

InvertedFlatListWithRef.displayName = 'InvertedFlatListWithRef';

export default InvertedFlatListWithRef;
export default forwardRef(InvertedFlatList);

0 comments on commit ca05400

Please sign in to comment.