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 = {
|
static contextTypes = {
|
||||||
virtualizedListCellRenderer: PropTypes.shape({
|
virtualizedCell: PropTypes.shape({
|
||||||
cellKey: PropTypes.string,
|
cellKey: PropTypes.string,
|
||||||
}),
|
}),
|
||||||
virtualizedList: PropTypes.shape({
|
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 = () => {
|
_getScrollMetrics = () => {
|
||||||
return this._scrollMetrics;
|
return this._scrollMetrics;
|
||||||
};
|
};
|
||||||
|
@ -559,10 +566,8 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
if (this._isNestedWithSameOrientation()) {
|
if (this._isNestedWithSameOrientation()) {
|
||||||
const storedState = this.context.virtualizedList.registerAsNestedChild({
|
const storedState = this.context.virtualizedList.registerAsNestedChild({
|
||||||
cellKey: this.context.virtualizedListCellRenderer.cellKey,
|
cellKey: this._getCellKey(),
|
||||||
key:
|
key: this.props.listKey || this._getCellKey(),
|
||||||
this.props.listKey ||
|
|
||||||
this.context.virtualizedListCellRenderer.cellKey,
|
|
||||||
ref: this,
|
ref: this,
|
||||||
});
|
});
|
||||||
if (storedState) {
|
if (storedState) {
|
||||||
|
@ -575,8 +580,6 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
||||||
this.state = initialState;
|
this.state = initialState;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (this.props.initialScrollIndex) {
|
if (this.props.initialScrollIndex) {
|
||||||
this._initialScrollIndexTimeout = setTimeout(
|
this._initialScrollIndexTimeout = setTimeout(
|
||||||
|
@ -593,9 +596,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
if (this._isNestedWithSameOrientation()) {
|
if (this._isNestedWithSameOrientation()) {
|
||||||
this.context.virtualizedList.unregisterAsNestedChild({
|
this.context.virtualizedList.unregisterAsNestedChild({
|
||||||
key:
|
key: this.props.listKey || this._getCellKey(),
|
||||||
this.props.listKey ||
|
|
||||||
this.context.virtualizedListCellRenderer.cellKey,
|
|
||||||
state: {
|
state: {
|
||||||
first: this.state.first,
|
first: this.state.first,
|
||||||
last: this.state.last,
|
last: this.state.last,
|
||||||
|
@ -743,12 +744,13 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
||||||
<ListHeaderComponent />
|
<ListHeaderComponent />
|
||||||
);
|
);
|
||||||
cells.push(
|
cells.push(
|
||||||
<View
|
<VirtualizedCellWrapper
|
||||||
key="$header"
|
cellKey={this._getCellKey() + '-header'}
|
||||||
onLayout={this._onLayoutHeader}
|
key="$header">
|
||||||
style={inversionStyle}>
|
<View onLayout={this._onLayoutHeader} style={inversionStyle}>
|
||||||
{element}
|
{element}
|
||||||
</View>,
|
</View>
|
||||||
|
</VirtualizedCellWrapper>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const itemCount = this.props.getItemCount(data);
|
const itemCount = this.props.getItemCount(data);
|
||||||
|
@ -867,12 +869,13 @@ class VirtualizedList extends React.PureComponent<Props, State> {
|
||||||
<ListFooterComponent />
|
<ListFooterComponent />
|
||||||
);
|
);
|
||||||
cells.push(
|
cells.push(
|
||||||
<View
|
<VirtualizedCellWrapper
|
||||||
key="$footer"
|
cellKey={this._getCellKey() + '-footer'}
|
||||||
onLayout={this._onLayoutFooter}
|
key="$footer">
|
||||||
style={inversionStyle}>
|
<View onLayout={this._onLayoutFooter} style={inversionStyle}>
|
||||||
{element}
|
{element}
|
||||||
</View>,
|
</View>
|
||||||
|
</VirtualizedCellWrapper>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const scrollProps = {
|
const scrollProps = {
|
||||||
|
@ -1522,14 +1525,14 @@ class CellRenderer extends React.Component<
|
||||||
};
|
};
|
||||||
|
|
||||||
static childContextTypes = {
|
static childContextTypes = {
|
||||||
virtualizedListCellRenderer: PropTypes.shape({
|
virtualizedCell: PropTypes.shape({
|
||||||
cellKey: PropTypes.string,
|
cellKey: PropTypes.string,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
getChildContext() {
|
getChildContext() {
|
||||||
return {
|
return {
|
||||||
virtualizedListCellRenderer: {
|
virtualizedCell: {
|
||||||
cellKey: this.props.cellKey,
|
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({
|
const styles = StyleSheet.create({
|
||||||
verticallyInverted: {
|
verticallyInverted: {
|
||||||
transform: [{scaleY: -1}],
|
transform: [{scaleY: -1}],
|
||||||
|
|
Loading…
Reference in New Issue