Fix virtualized cell keys for list headers and footers
Summary: The change enabling virtualization in nested lists contained a hidden assumption that nested lists would only appear within the *cells* of a parent list. If a list header or footer component contains a `VirtualizedList`, that child list won't be wrapped in a `CellRenderer` component and therefore won't have access to `virtualizedCellRenderer` through its context. This causes an error when the child list tries to access the `cellKey` property on an undefined object. This change wraps the header/footer views in a `VirtualizedCellWrapper` component which supplies that context properly. Reviewed By: sahrens Differential Revision: D6603342 fbshipit-source-id: 4d2d82f04947048a16ec9968121d8ecc8c95655a
This commit is contained in:
parent
f1055bcac8
commit
a010a0cebd
|
@ -432,7 +432,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
|||
};
|
||||
|
||||
static contextTypes = {
|
||||
virtualizedListCellRenderer: PropTypes.shape({
|
||||
virtualizedCell: PropTypes.shape({
|
||||
cellKey: PropTypes.string,
|
||||
}),
|
||||
virtualizedList: PropTypes.shape({
|
||||
|
@ -466,6 +466,13 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
|||
};
|
||||
}
|
||||
|
||||
_getCellKey(): string {
|
||||
return (
|
||||
(this.context.virtualizedCell && this.context.virtualizedCell.cellKey) ||
|
||||
'rootList'
|
||||
);
|
||||
}
|
||||
|
||||
_getScrollMetrics = () => {
|
||||
return this._scrollMetrics;
|
||||
};
|
||||
|
@ -559,10 +566,8 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
|||
|
||||
if (this._isNestedWithSameOrientation()) {
|
||||
const storedState = this.context.virtualizedList.registerAsNestedChild({
|
||||
cellKey: this.context.virtualizedListCellRenderer.cellKey,
|
||||
key:
|
||||
this.props.listKey ||
|
||||
this.context.virtualizedListCellRenderer.cellKey,
|
||||
cellKey: this._getCellKey(),
|
||||
key: this.props.listKey || this._getCellKey(),
|
||||
ref: this,
|
||||
});
|
||||
if (storedState) {
|
||||
|
@ -575,8 +580,6 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
|||
this.state = initialState;
|
||||
}
|
||||
|
||||
componentWillMount() {}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.initialScrollIndex) {
|
||||
this._initialScrollIndexTimeout = setTimeout(
|
||||
|
@ -593,9 +596,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
|||
componentWillUnmount() {
|
||||
if (this._isNestedWithSameOrientation()) {
|
||||
this.context.virtualizedList.unregisterAsNestedChild({
|
||||
key:
|
||||
this.props.listKey ||
|
||||
this.context.virtualizedListCellRenderer.cellKey,
|
||||
key: this.props.listKey || this._getCellKey(),
|
||||
state: {
|
||||
first: this.state.first,
|
||||
last: this.state.last,
|
||||
|
@ -743,12 +744,13 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
|||
<ListHeaderComponent />
|
||||
);
|
||||
cells.push(
|
||||
<View
|
||||
key="$header"
|
||||
onLayout={this._onLayoutHeader}
|
||||
style={inversionStyle}>
|
||||
{element}
|
||||
</View>,
|
||||
<VirtualizedCellWrapper
|
||||
cellKey={this._getCellKey() + '-header'}
|
||||
key="$header">
|
||||
<View onLayout={this._onLayoutHeader} style={inversionStyle}>
|
||||
{element}
|
||||
</View>
|
||||
</VirtualizedCellWrapper>,
|
||||
);
|
||||
}
|
||||
const itemCount = this.props.getItemCount(data);
|
||||
|
@ -867,12 +869,13 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
|||
<ListFooterComponent />
|
||||
);
|
||||
cells.push(
|
||||
<View
|
||||
key="$footer"
|
||||
onLayout={this._onLayoutFooter}
|
||||
style={inversionStyle}>
|
||||
{element}
|
||||
</View>,
|
||||
<VirtualizedCellWrapper
|
||||
cellKey={this._getCellKey() + '-footer'}
|
||||
key="$footer">
|
||||
<View onLayout={this._onLayoutFooter} style={inversionStyle}>
|
||||
{element}
|
||||
</View>
|
||||
</VirtualizedCellWrapper>,
|
||||
);
|
||||
}
|
||||
const scrollProps = {
|
||||
|
@ -1522,14 +1525,14 @@ class CellRenderer extends React.Component<
|
|||
};
|
||||
|
||||
static childContextTypes = {
|
||||
virtualizedListCellRenderer: PropTypes.shape({
|
||||
virtualizedCell: PropTypes.shape({
|
||||
cellKey: PropTypes.string,
|
||||
}),
|
||||
};
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
virtualizedListCellRenderer: {
|
||||
virtualizedCell: {
|
||||
cellKey: this.props.cellKey,
|
||||
},
|
||||
};
|
||||
|
@ -1621,6 +1624,29 @@ class CellRenderer extends React.Component<
|
|||
}
|
||||
}
|
||||
|
||||
class VirtualizedCellWrapper extends React.Component<{
|
||||
cellKey: string,
|
||||
children: React.Node,
|
||||
}> {
|
||||
static childContextTypes = {
|
||||
virtualizedCell: PropTypes.shape({
|
||||
cellKey: PropTypes.string,
|
||||
}),
|
||||
};
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
virtualizedCell: {
|
||||
cellKey: this.props.cellKey,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
verticallyInverted: {
|
||||
transform: [{scaleY: -1}],
|
||||
|
|
Loading…
Reference in New Issue