RN: Minor Flow Cleanup in FlatList

Summary:
Cleans up a few minor Flow suppression comments in `FlatList`. This reveals a new Flow error that is the result of `FlatList`'s props object being inexact whereas `VirtualizedList`'s props object is exact. For now, I introduce another -- but more specific -- Flow suppression for that type error.

The code changes should not have any consequential behavior change.

Changelog:
[Internal]

Reviewed By: NickGerleman

Differential Revision: D38646228

fbshipit-source-id: f4f9b0ad95323157ff1519353b38e8486adc841d
This commit is contained in:
Tim Yung
2022-08-12 17:16:40 -07:00
committed by Facebook GitHub Bot
parent 23429330a6
commit 459b25ce43
2 changed files with 70 additions and 83 deletions
+46 -54
View File
@@ -523,30 +523,26 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
}
};
// $FlowFixMe[missing-local-annot]
_keyExtractor = (items: ItemT | Array<ItemT>, index: number) => {
_keyExtractor = (items: ItemT | Array<ItemT>, index: number): string => {
const numColumns = numColumnsOrDefault(this.props.numColumns);
const keyExtractor = this.props.keyExtractor ?? defaultKeyExtractor;
if (numColumns > 1) {
if (Array.isArray(items)) {
return items
.map((item, kk) =>
keyExtractor(((item: $FlowFixMe): ItemT), index * numColumns + kk),
)
.join(':');
} else {
invariant(
Array.isArray(items),
'FlatList: Encountered internal consistency error, expected each item to consist of an ' +
'array with 1-%s columns; instead, received a single item.',
numColumns,
);
}
} else {
// $FlowFixMe[incompatible-call] Can't call keyExtractor with an array
return keyExtractor(items, index);
invariant(
Array.isArray(items),
'FlatList: Encountered internal consistency error, expected each item to consist of an ' +
'array with 1-%s columns; instead, received a single item.',
numColumns,
);
return items
.map((item, kk) =>
keyExtractor(((item: $FlowFixMe): ItemT), index * numColumns + kk),
)
.join(':');
}
// $FlowFixMe[incompatible-call] Can't call keyExtractor with an array
return keyExtractor(items, index);
};
_pushMultiColumnViewable(arr: Array<ViewToken>, v: ViewToken): void {
@@ -599,11 +595,7 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
) => {
const cols = numColumnsOrDefault(numColumns);
let virtualizedListRenderKey = ListItemComponent
? 'ListItemComponent'
: 'renderItem';
const renderer = (props: RenderItemProps<ItemT>): React.Node => {
const render = (props: RenderItemProps<ItemT>): React.Node => {
if (ListItemComponent) {
// $FlowFixMe[not-a-component] Component isn't valid
// $FlowFixMe[incompatible-type-arg] Component isn't valid
@@ -617,37 +609,36 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
}
};
return {
/* $FlowFixMe[invalid-computed-prop] (>=0.111.0 site=react_native_fb)
* This comment suppresses an error found when Flow v0.111 was deployed.
* To see the error, delete this comment and run Flow. */
[virtualizedListRenderKey]: (info: RenderItemProps<ItemT>) => {
if (cols > 1) {
const {item, index} = info;
invariant(
Array.isArray(item),
'Expected array of items with numColumns > 1',
);
return (
<View style={StyleSheet.compose(styles.row, columnWrapperStyle)}>
{item.map((it, kk) => {
const element = renderer({
// $FlowFixMe[incompatible-call]
item: it,
index: index * cols + kk,
separators: info.separators,
});
return element != null ? (
<React.Fragment key={kk}>{element}</React.Fragment>
) : null;
})}
</View>
);
} else {
return renderer(info);
}
},
const renderProp = (info: RenderItemProps<ItemT>) => {
if (cols > 1) {
const {item, index} = info;
invariant(
Array.isArray(item),
'Expected array of items with numColumns > 1',
);
return (
<View style={StyleSheet.compose(styles.row, columnWrapperStyle)}>
{item.map((it, kk) => {
const element = render({
// $FlowFixMe[incompatible-call]
item: it,
index: index * cols + kk,
separators: info.separators,
});
return element != null ? (
<React.Fragment key={kk}>{element}</React.Fragment>
) : null;
})}
</View>
);
} else {
return render(info);
}
};
return ListItemComponent
? {ListItemComponent: renderProp}
: {renderItem: renderProp};
};
// $FlowFixMe[missing-local-annot]
@@ -665,6 +656,7 @@ class FlatList<ItemT> extends React.PureComponent<Props<ItemT>, void> {
const renderer = strictMode ? this._memoizedRenderer : this._renderer;
return (
// $FlowFixMe[incompatible-exact] - `restProps` (`Props`) is inexact.
<VirtualizedList
{...restProps}
getItem={this._getItem}
@@ -12,6 +12,7 @@
import type {AnimatedComponentType} from 'react-native/Libraries/Animated/createAnimatedComponent';
import typeof FlatListType from 'react-native/Libraries/Lists/FlatList';
import type {RenderItemProps} from 'react-native/Libraries/Lists/VirtualizedListProps';
import type {RNTesterModuleExample} from '../../types/RNTesterTypes';
import * as React from 'react';
@@ -94,7 +95,7 @@ class FlatListExample extends React.PureComponent<Props, State> {
};
_onChangeScrollToIndex = (text: mixed) => {
this._listRef.scrollToIndex({viewPosition: 0.5, index: Number(text)});
this._listRef?.scrollToIndex({viewPosition: 0.5, index: Number(text)});
};
// $FlowFixMe[missing-local-annot]
@@ -111,7 +112,7 @@ class FlatListExample extends React.PureComponent<Props, State> {
);
componentDidUpdate() {
this._listRef.recordInteraction(); // e.g. flipping logViewable switch
this._listRef?.recordInteraction(); // e.g. flipping logViewable switch
}
_setBooleanValue: string => boolean => void = key => value =>
@@ -270,7 +271,7 @@ class FlatListExample extends React.PureComponent<Props, State> {
React.ElementConfig<FlatListType>,
React.ElementRef<FlatListType>,
>,
>,
> | null,
) => {
this._listRef = ref;
};
@@ -297,31 +298,25 @@ class FlatListExample extends React.PureComponent<Props, State> {
_onRefresh = () => Alert.alert('onRefresh: nothing to refresh :P');
// $FlowFixMe[missing-local-annot]
_renderItemComponent = () => {
const flatListPropKey = this.state.useFlatListItemComponent
? 'ListItemComponent'
: 'renderItem';
return {
renderItem: undefined,
/* $FlowFixMe[invalid-computed-prop] (>=0.111.0 site=react_native_fb)
* This comment suppresses an error found when Flow v0.111 was deployed.
* To see the error, delete this comment and run Flow. */
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by
* Flow's LTI update could not be added via codemod */
[flatListPropKey]: ({item, separators}) => {
return (
<ItemComponent
item={item}
horizontal={this.state.horizontal}
fixedHeight={this.state.fixedHeight}
onPress={this._onPressCallback()}
onShowUnderlay={separators.highlight}
onHideUnderlay={separators.unhighlight}
textSelectable={this.state.textSelectable}
/>
);
},
const renderProp = ({item, separators}: RenderItemProps<Item>) => {
return (
<ItemComponent
item={item}
horizontal={this.state.horizontal}
fixedHeight={this.state.fixedHeight}
onPress={this._onPressCallback()}
onShowUnderlay={separators.highlight}
onHideUnderlay={separators.unhighlight}
textSelectable={this.state.textSelectable}
/>
);
};
return this.state.useFlatListItemComponent
? {
renderItem: undefined,
ListItemComponent: renderProp,
}
: {renderItem: renderProp};
};
// This is called when items change viewability by scrolling into or out of
// the viewable area.
@@ -346,7 +341,7 @@ class FlatListExample extends React.PureComponent<Props, State> {
};
_pressItem = (key: string) => {
this._listRef && this._listRef.recordInteraction();
this._listRef?.recordInteraction();
const index = Number(key);
const itemState = pressItem(this.state.data[index]);
this.setState(state => ({
@@ -359,7 +354,7 @@ class FlatListExample extends React.PureComponent<Props, State> {
}));
};
_listRef: React.ElementRef<typeof Animated.FlatList>;
_listRef: React.ElementRef<typeof Animated.FlatList> | null;
}
const styles = StyleSheet.create({