Skip to content

Commit a010a0c

Browse files
logandanielsfacebook-github-bot
authored andcommittedDec 19, 2017
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
1 parent f1055bc commit a010a0c

File tree

1 file changed

+50
-24
lines changed

1 file changed

+50
-24
lines changed
 

‎Libraries/Lists/VirtualizedList.js

+50-24
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
432432
};
433433

434434
static contextTypes = {
435-
virtualizedListCellRenderer: PropTypes.shape({
435+
virtualizedCell: PropTypes.shape({
436436
cellKey: PropTypes.string,
437437
}),
438438
virtualizedList: PropTypes.shape({
@@ -466,6 +466,13 @@ class VirtualizedList extends React.PureComponent<Props, State> {
466466
};
467467
}
468468

469+
_getCellKey(): string {
470+
return (
471+
(this.context.virtualizedCell && this.context.virtualizedCell.cellKey) ||
472+
'rootList'
473+
);
474+
}
475+
469476
_getScrollMetrics = () => {
470477
return this._scrollMetrics;
471478
};
@@ -559,10 +566,8 @@ class VirtualizedList extends React.PureComponent<Props, State> {
559566

560567
if (this._isNestedWithSameOrientation()) {
561568
const storedState = this.context.virtualizedList.registerAsNestedChild({
562-
cellKey: this.context.virtualizedListCellRenderer.cellKey,
563-
key:
564-
this.props.listKey ||
565-
this.context.virtualizedListCellRenderer.cellKey,
569+
cellKey: this._getCellKey(),
570+
key: this.props.listKey || this._getCellKey(),
566571
ref: this,
567572
});
568573
if (storedState) {
@@ -575,8 +580,6 @@ class VirtualizedList extends React.PureComponent<Props, State> {
575580
this.state = initialState;
576581
}
577582

578-
componentWillMount() {}
579-
580583
componentDidMount() {
581584
if (this.props.initialScrollIndex) {
582585
this._initialScrollIndexTimeout = setTimeout(
@@ -593,9 +596,7 @@ class VirtualizedList extends React.PureComponent<Props, State> {
593596
componentWillUnmount() {
594597
if (this._isNestedWithSameOrientation()) {
595598
this.context.virtualizedList.unregisterAsNestedChild({
596-
key:
597-
this.props.listKey ||
598-
this.context.virtualizedListCellRenderer.cellKey,
599+
key: this.props.listKey || this._getCellKey(),
599600
state: {
600601
first: this.state.first,
601602
last: this.state.last,
@@ -743,12 +744,13 @@ class VirtualizedList extends React.PureComponent<Props, State> {
743744
<ListHeaderComponent />
744745
);
745746
cells.push(
746-
<View
747-
key="$header"
748-
onLayout={this._onLayoutHeader}
749-
style={inversionStyle}>
750-
{element}
751-
</View>,
747+
<VirtualizedCellWrapper
748+
cellKey={this._getCellKey() + '-header'}
749+
key="$header">
750+
<View onLayout={this._onLayoutHeader} style={inversionStyle}>
751+
{element}
752+
</View>
753+
</VirtualizedCellWrapper>,
752754
);
753755
}
754756
const itemCount = this.props.getItemCount(data);
@@ -867,12 +869,13 @@ class VirtualizedList extends React.PureComponent<Props, State> {
867869
<ListFooterComponent />
868870
);
869871
cells.push(
870-
<View
871-
key="$footer"
872-
onLayout={this._onLayoutFooter}
873-
style={inversionStyle}>
874-
{element}
875-
</View>,
872+
<VirtualizedCellWrapper
873+
cellKey={this._getCellKey() + '-footer'}
874+
key="$footer">
875+
<View onLayout={this._onLayoutFooter} style={inversionStyle}>
876+
{element}
877+
</View>
878+
</VirtualizedCellWrapper>,
876879
);
877880
}
878881
const scrollProps = {
@@ -1522,14 +1525,14 @@ class CellRenderer extends React.Component<
15221525
};
15231526

15241527
static childContextTypes = {
1525-
virtualizedListCellRenderer: PropTypes.shape({
1528+
virtualizedCell: PropTypes.shape({
15261529
cellKey: PropTypes.string,
15271530
}),
15281531
};
15291532

15301533
getChildContext() {
15311534
return {
1532-
virtualizedListCellRenderer: {
1535+
virtualizedCell: {
15331536
cellKey: this.props.cellKey,
15341537
},
15351538
};
@@ -1621,6 +1624,29 @@ class CellRenderer extends React.Component<
16211624
}
16221625
}
16231626

1627+
class VirtualizedCellWrapper extends React.Component<{
1628+
cellKey: string,
1629+
children: React.Node,
1630+
}> {
1631+
static childContextTypes = {
1632+
virtualizedCell: PropTypes.shape({
1633+
cellKey: PropTypes.string,
1634+
}),
1635+
};
1636+
1637+
getChildContext() {
1638+
return {
1639+
virtualizedCell: {
1640+
cellKey: this.props.cellKey,
1641+
},
1642+
};
1643+
}
1644+
1645+
render() {
1646+
return this.props.children;
1647+
}
1648+
}
1649+
16241650
const styles = StyleSheet.create({
16251651
verticallyInverted: {
16261652
transform: [{scaleY: -1}],

0 commit comments

Comments
 (0)
Please sign in to comment.