From 459b25ce43b671bb1a3bfb5025c8e9af31a9214e Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Fri, 12 Aug 2022 17:16:40 -0700 Subject: [PATCH] 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 --- Libraries/Lists/FlatList.js | 100 ++++++++---------- .../js/examples/FlatList/FlatList-basic.js | 53 +++++----- 2 files changed, 70 insertions(+), 83 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index c09b289d3cc..2315e1721d3 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -523,30 +523,26 @@ class FlatList extends React.PureComponent, void> { } }; - // $FlowFixMe[missing-local-annot] - _keyExtractor = (items: ItemT | Array, index: number) => { + _keyExtractor = (items: ItemT | Array, 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, v: ViewToken): void { @@ -599,11 +595,7 @@ class FlatList extends React.PureComponent, void> { ) => { const cols = numColumnsOrDefault(numColumns); - let virtualizedListRenderKey = ListItemComponent - ? 'ListItemComponent' - : 'renderItem'; - - const renderer = (props: RenderItemProps): React.Node => { + const render = (props: RenderItemProps): 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 extends React.PureComponent, 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) => { - if (cols > 1) { - const {item, index} = info; - invariant( - Array.isArray(item), - 'Expected array of items with numColumns > 1', - ); - return ( - - {item.map((it, kk) => { - const element = renderer({ - // $FlowFixMe[incompatible-call] - item: it, - index: index * cols + kk, - separators: info.separators, - }); - return element != null ? ( - {element} - ) : null; - })} - - ); - } else { - return renderer(info); - } - }, + const renderProp = (info: RenderItemProps) => { + if (cols > 1) { + const {item, index} = info; + invariant( + Array.isArray(item), + 'Expected array of items with numColumns > 1', + ); + return ( + + {item.map((it, kk) => { + const element = render({ + // $FlowFixMe[incompatible-call] + item: it, + index: index * cols + kk, + separators: info.separators, + }); + return element != null ? ( + {element} + ) : null; + })} + + ); + } else { + return render(info); + } }; + + return ListItemComponent + ? {ListItemComponent: renderProp} + : {renderItem: renderProp}; }; // $FlowFixMe[missing-local-annot] @@ -665,6 +656,7 @@ class FlatList extends React.PureComponent, void> { const renderer = strictMode ? this._memoizedRenderer : this._renderer; return ( + // $FlowFixMe[incompatible-exact] - `restProps` (`Props`) is inexact. { }; _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 { ); 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 { React.ElementConfig, React.ElementRef, >, - >, + > | null, ) => { this._listRef = ref; }; @@ -297,31 +298,25 @@ class FlatListExample extends React.PureComponent { _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 ( - - ); - }, + const renderProp = ({item, separators}: RenderItemProps) => { + return ( + + ); }; + 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 { }; _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 { })); }; - _listRef: React.ElementRef; + _listRef: React.ElementRef | null; } const styles = StyleSheet.create({