Skip to content

Commit

Permalink
Fix types + documentation for CellRendererComponent
Browse files Browse the repository at this point in the history
Summary:
CellRendererComponent can be given a more useful description, and more constrained type, to ensure it is used more correctly.

Changelog:
[General][Fixed] - Fix types + documentation for CellRendererComponent

Reviewed By: yungsters

Differential Revision: D43925572

fbshipit-source-id: 26aae6a2df989993c97709ffbf1544df7cbae036
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Mar 14, 2023
1 parent ccbbcaa commit 2d41e66
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 39 deletions.
21 changes: 20 additions & 1 deletion packages/virtualized-lists/Lists/VirtualizedList.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ export type ListRenderItem<ItemT> = (
info: ListRenderItemInfo<ItemT>,
) => React.ReactElement | null;

export interface CellRendererProps<ItemT> {
cellKey: string;
children: React.ReactNode;
index: number;
item: ItemT;
onFocusCapture?: ((event: FocusEvent) => void) | undefined;
onLayout?: ((event: LayoutChangeEvent) => void) | undefined;
style: StyleProp<ViewStyle> | undefined;
}

/**
* @see https://reactnative.dev/docs/virtualizedlist
*/
Expand Down Expand Up @@ -370,5 +380,14 @@ export interface VirtualizedListWithoutRenderItemProps<ItemT>
*/
windowSize?: number | undefined;

CellRendererComponent?: React.ComponentType<any> | undefined;
/**
* CellRendererComponent allows customizing how cells rendered by
* `renderItem`/`ListItemComponent` are wrapped when placed into the
* underlying ScrollView. This component must accept event handlers which
* notify VirtualizedList of changes within the cell.
*/
CellRendererComponent?:
| React.ComponentType<CellRendererProps<ItemT>>
| null
| undefined;
}
13 changes: 9 additions & 4 deletions packages/virtualized-lists/Lists/VirtualizedList.js
Original file line number Diff line number Diff line change
Expand Up @@ -748,36 +748,41 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
const end = getItemCount(data) - 1;
let prevCellKey;
last = Math.min(end, last);

for (let ii = first; ii <= last; ii++) {
const item = getItem(data, ii);
const key = this._keyExtractor(item, ii, this.props);

this._indicesToKeys.set(ii, key);
if (stickyIndicesFromProps.has(ii + stickyOffset)) {
stickyHeaderIndices.push(cells.length);
}

const shouldListenForLayout =
getItemLayout == null || debug || this._fillRateHelper.enabled();

cells.push(
<CellRenderer
CellRendererComponent={CellRendererComponent}
ItemSeparatorComponent={ii < end ? ItemSeparatorComponent : undefined}
ListItemComponent={ListItemComponent}
cellKey={key}
debug={debug}
fillRateHelper={this._fillRateHelper}
getItemLayout={getItemLayout}
horizontal={horizontal}
index={ii}
inversionStyle={inversionStyle}
item={item}
key={key}
prevCellKey={prevCellKey}
onCellLayout={this._onCellLayout}
onUpdateSeparators={this._onUpdateSeparators}
onCellFocusCapture={e => this._onCellFocusCapture(key)}
onUnmount={this._onCellUnmount}
ref={ref => {
this._cellRefs[key] = ref;
}}
renderItem={renderItem}
{...(shouldListenForLayout && {
onCellLayout: this._onCellLayout,
})}
/>,
);
prevCellKey = key;
Expand Down
42 changes: 11 additions & 31 deletions packages/virtualized-lists/Lists/VirtualizedListCellRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,25 @@ import type {
FocusEvent,
LayoutEvent,
} from 'react-native/Libraries/Types/CoreEventTypes';
import type FillRateHelper from './FillRateHelper';
import type {RenderItemType} from './VirtualizedListProps';
import type {CellRendererProps, RenderItemType} from './VirtualizedListProps';

import {View, StyleSheet} from 'react-native';
import {VirtualizedListCellContextProvider} from './VirtualizedListContext.js';
import invariant from 'invariant';
import * as React from 'react';

export type Props<ItemT> = {
CellRendererComponent?: ?React.ComponentType<any>,
CellRendererComponent?: ?React.ComponentType<CellRendererProps<ItemT>>,
ItemSeparatorComponent: ?React.ComponentType<
any | {highlighted: boolean, leadingItem: ?ItemT},
>,
ListItemComponent?: ?(React.ComponentType<any> | React.Element<any>),
cellKey: string,
debug?: ?boolean,
fillRateHelper: FillRateHelper,
getItemLayout?: (
data: any,
index: number,
) => {
length: number,
offset: number,
index: number,
...
},
horizontal: ?boolean,
index: number,
inversionStyle: ViewStyleProp,
item: ItemT,
onCellLayout: (event: LayoutEvent, cellKey: string, index: number) => void,
onCellLayout?: (event: LayoutEvent, cellKey: string, index: number) => void,
onCellFocusCapture?: (event: FocusEvent) => void,
onUnmount: (cellKey: string) => void,
onUpdateSeparators: (
Expand Down Expand Up @@ -181,14 +169,13 @@ export default class CellRenderer<ItemT> extends React.Component<
CellRendererComponent,
ItemSeparatorComponent,
ListItemComponent,
debug,
fillRateHelper,
getItemLayout,
cellKey,
horizontal,
item,
index,
inversionStyle,
onCellFocusCapture,
onCellLayout,
renderItem,
} = this.props;
const element = this._renderElement(
Expand All @@ -198,11 +185,6 @@ export default class CellRenderer<ItemT> extends React.Component<
index,
);

const onLayout =
(getItemLayout && !debug && !fillRateHelper.enabled()) ||
!this.props.onCellLayout
? undefined
: this._onLayout;
// NOTE: that when this is a sticky header, `onLayout` will get automatically extracted and
// called explicitly by `ScrollViewStickyHeader`.
const itemSeparator: React.Node = React.isValidElement(
Expand All @@ -224,21 +206,19 @@ export default class CellRenderer<ItemT> extends React.Component<
const result = !CellRendererComponent ? (
<View
style={cellStyle}
onLayout={onLayout}
onFocusCapture={onCellFocusCapture}
/* $FlowFixMe[incompatible-type-arg] (>=0.89.0 site=react_native_fb) *
This comment suppresses an error found when Flow v0.89 was deployed. *
To see the error, delete this comment and run Flow. */
>
{...(onCellLayout && {onLayout: this._onLayout})}>
{element}
{itemSeparator}
</View>
) : (
<CellRendererComponent
{...this.props}
cellKey={cellKey}
index={index}
item={item}
style={cellStyle}
onLayout={onLayout}
onFocusCapture={onCellFocusCapture}>
onFocusCapture={onCellFocusCapture}
{...(onCellLayout && {onLayout: this._onLayout})}>
{element}
{itemSeparator}
</CellRendererComponent>
Expand Down
22 changes: 19 additions & 3 deletions packages/virtualized-lists/Lists/VirtualizedListProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
*/

import {typeof ScrollView} from 'react-native';
import type {
FocusEvent,
LayoutEvent,
} from 'react-native/Libraries/Types/CoreEventTypes';
import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
import type {
ViewabilityConfig,
Expand All @@ -34,6 +38,16 @@ export type RenderItemProps<ItemT> = {
...
};

export type CellRendererProps<ItemT> = $ReadOnly<{
cellKey: string,
children: React.Node,
index: number,
item: ItemT,
onFocusCapture?: (event: FocusEvent) => void,
onLayout?: (event: LayoutEvent) => void,
style: ViewStyleProp,
}>;

export type RenderItemType<ItemT> = (
info: RenderItemProps<ItemT>,
) => React.Node;
Expand Down Expand Up @@ -102,10 +116,12 @@ type OptionalProps = {|
inverted?: ?boolean,
keyExtractor?: ?(item: Item, index: number) => string,
/**
* Each cell is rendered using this element. Can be a React Component Class,
* or a render function. Defaults to using View.
* CellRendererComponent allows customizing how cells rendered by
* `renderItem`/`ListItemComponent` are wrapped when placed into the
* underlying ScrollView. This component must accept event handlers which
* notify VirtualizedList of changes within the cell.
*/
CellRendererComponent?: ?React.ComponentType<any>,
CellRendererComponent?: ?React.ComponentType<CellRendererProps<Item>>,
/**
* Rendered in between each item, but not at the top or bottom. By default, `highlighted` and
* `leadingItem` props are provided. `renderItem` provides `separators.highlight`/`unhighlight`
Expand Down
1 change: 1 addition & 0 deletions packages/virtualized-lists/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type {
ViewabilityConfigCallbackPair,
} from './Lists/ViewabilityHelper';
export type {
CellRendererProps,
RenderItemProps,
RenderItemType,
Separators,
Expand Down

0 comments on commit 2d41e66

Please sign in to comment.