Skip to content

Commit

Permalink
Fix inverted FlatList (#5295)
Browse files Browse the repository at this point in the history
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

This PR changes how reanimated treats inverted `FlatLists`. In #3765 our
implementation was changed to mimic the react-native behavior by
assigning a special style that reverts the cell inversion (inverted
FlatList flips the entire view and then flips back every cell). In
react-native@0.72.4 the inversion style was
[changed](facebook/react-native#38073) on
android due to some performance issues. That change combined with our
implementation was causing the cell to remain inverted on android (since
both styles were being applied). This PR changes our implementation to
instead allow the `CellRendererComponent` to receive a style prop,
making react solely responsible for the cell inversion.


## Test plan
Check whether the Inverted FlatList Example behaves properly on android.
I tested the example on all rn versions from rn@0.69
  • Loading branch information
bartlomiejbloniarz authored Oct 30, 2023
1 parent fe587cf commit c11b671
Showing 1 changed file with 12 additions and 25 deletions.
37 changes: 12 additions & 25 deletions src/reanimated2/component/FlatList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { ForwardedRef } from 'react';
import React, { Component, forwardRef } from 'react';
import type { FlatListProps, LayoutChangeEvent } from 'react-native';
import { FlatList, StyleSheet } from 'react-native';
import { FlatList } from 'react-native';
import { AnimatedView } from './View';
import { createAnimatedComponent } from '../../createAnimatedComponent';
import type { ILayoutAnimationBuilder } from '../layoutReanimation/animationBuilder/commonTypes';
Expand All @@ -12,31 +12,29 @@ import { LayoutAnimationConfig } from './LayoutAnimationConfig';

const AnimatedFlatList = createAnimatedComponent(FlatList as any) as any;

interface AnimatedFlatListProps {
interface CellRendererComponentProps {
onLayout: (event: LayoutChangeEvent) => void;
// implicit `children` prop has been removed in @types/react^18.0.0
children: React.ReactNode;
inverted?: boolean;
horizontal?: boolean;
style?: StyleProps;
}

const createCellRenderer = (
itemLayoutAnimation?: ILayoutAnimationBuilder,
cellStyle?: StyleProps
const createCellRendererComponent = (
itemLayoutAnimation?: ILayoutAnimationBuilder
) => {
const cellRenderer = (props: AnimatedFlatListProps) => {
const CellRendererComponent = (props: CellRendererComponentProps) => {
return (
<AnimatedView
// TODO TYPESCRIPT This is temporary cast is to get rid of .d.ts file.
layout={itemLayoutAnimation as any}
onLayout={props.onLayout}
style={cellStyle}>
style={props.style}>
{props.children}
</AnimatedView>
);
};

return cellRenderer;
return CellRendererComponent;
};

interface ReanimatedFlatListPropsWithLayout<T> extends FlatListProps<T> {
Expand All @@ -63,12 +61,6 @@ export const ReanimatedFlatList = forwardRef(
const { itemLayoutAnimation, skipEnteringExitingAnimations, ...restProps } =
props;

const cellStyle = restProps?.inverted
? restProps?.horizontal
? styles.horizontallyInverted
: styles.verticallyInverted
: undefined;

// Set default scrollEventThrottle, because user expects
// to have continuous scroll events and
// react-native defaults it to 50 for FlatLists.
Expand All @@ -78,16 +70,16 @@ export const ReanimatedFlatList = forwardRef(
restProps.scrollEventThrottle = 1;
}

const cellRenderer = React.useMemo(
() => createCellRenderer(itemLayoutAnimation, cellStyle),
[cellStyle]
const CellRendererComponent = React.useMemo(
() => createCellRendererComponent(itemLayoutAnimation),
[]
);

const animatedFlatList = (
<AnimatedFlatList
ref={ref}
{...restProps}
CellRendererComponent={cellRenderer}
CellRendererComponent={CellRendererComponent}
/>
);

Expand All @@ -103,10 +95,5 @@ export const ReanimatedFlatList = forwardRef(
}
) as unknown as ReanimatedFlatList<any>;

const styles = StyleSheet.create({
verticallyInverted: { transform: [{ scaleY: -1 }] },
horizontallyInverted: { transform: [{ scaleX: -1 }] },
});

export type ReanimatedFlatList<T> = typeof ReanimatedFlatListClass<T> &
FlatList<T>;

0 comments on commit c11b671

Please sign in to comment.