Skip to content

Commit db061ea

Browse files
janicduplessisfacebook-github-bot
authored andcommitted
Don't wrap ListEmptyComponent in an extra view
Summary: A common UI pattern for list empty states is some text/images centered inside the visible part of the list. This is pretty hard to do currently because we wrap ListEmptyComponent with an extra view with no way to style it so we cannot just use `flex: 1` to make it fill the available space. - Added an example of ListEmptyComponent in the FlatList example in RNTester Before (no way to make ListEmptyComponent fill the space): <img width="377" alt="screen shot 2018-03-05 at 5 24 15 pm" src="https://user-images.githubusercontent.com/2677334/37003152-129db3ac-209a-11e8-9600-110f10d57144.png"> After: <img width="377" alt="screen shot 2018-03-05 at 5 09 20 pm" src="https://user-images.githubusercontent.com/2677334/37002809-e6971178-2098-11e8-8cf7-74bfb2f6a992.png"> - Tested some edge cases like returning null from the ListEmptyComponent - Tested in an app that uses FlatList + ListEmptyComponent [GENERAL] [MINOR] [VirtualizedList] - Don't wrap ListEmptyComponent in an extra view Closes #18206 Differential Revision: D7266274 Pulled By: sahrens fbshipit-source-id: 4636d2418474a4c86ac63e5e18a9afc391a518c5
1 parent 9737774 commit db061ea

File tree

4 files changed

+38
-20
lines changed

4 files changed

+38
-20
lines changed

Libraries/Lists/VirtualizedList.js

+14-12
Original file line numberDiff line numberDiff line change
@@ -850,23 +850,25 @@ class VirtualizedList extends React.PureComponent<Props, State> {
850850
);
851851
}
852852
} else if (ListEmptyComponent) {
853-
const element = React.isValidElement(ListEmptyComponent) ? (
853+
const element: React.Element<any> = (React.isValidElement(
854+
ListEmptyComponent,
855+
) ? (
854856
ListEmptyComponent
855857
) : (
856858
// $FlowFixMe
857859
<ListEmptyComponent />
858-
);
860+
): any);
859861
cells.push(
860-
<View
861-
key="$empty"
862-
onLayout={this._onLayoutEmpty}
863-
style={inversionStyle}>
864-
{/*
865-
Flow doesn't know this is a React.Element and not a React.Component
866-
$FlowFixMe https://fburl.com/b9xmtm09
867-
*/}
868-
{element}
869-
</View>,
862+
React.cloneElement(element, {
863+
key: '$empty',
864+
onLayout: event => {
865+
this._onLayoutEmpty(event);
866+
if (element.props.onLayout) {
867+
element.props.onLayout(event);
868+
}
869+
},
870+
style: [element.props.style, inversionStyle],
871+
}),
870872
);
871873
}
872874
if (ListFooterComponent) {

Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap

+1-6
Original file line numberDiff line numberDiff line change
@@ -683,12 +683,7 @@ exports[`VirtualizedList renders empty list with empty component 1`] = `
683683
>
684684
<header />
685685
</View>
686-
<View
687-
onLayout={[Function]}
688-
style={null}
689-
>
690-
<empty />
691-
</View>
686+
<empty />
692687
<View
693688
onLayout={[Function]}
694689
style={null}

RNTester/js/FlatListExample.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const {
2727
FooterComponent,
2828
HeaderComponent,
2929
ItemComponent,
30+
ListEmptyComponent,
3031
ItemSeparatorComponent,
3132
PlainInput,
3233
SeparatorComponent,
@@ -58,6 +59,7 @@ class FlatListExample extends React.PureComponent<{}, $FlowFixMeState> {
5859
fixedHeight: true,
5960
logViewable: false,
6061
virtualized: true,
62+
empty: false,
6163
};
6264

6365
_onChangeFilterText = (filterText) => {
@@ -109,8 +111,9 @@ class FlatListExample extends React.PureComponent<{}, $FlowFixMeState> {
109111
{renderSmallSwitchOption(this, 'virtualized')}
110112
{renderSmallSwitchOption(this, 'horizontal')}
111113
{renderSmallSwitchOption(this, 'fixedHeight')}
112-
{renderSmallSwitchOption(this, 'logViewable')}
114+
{renderSmallSwitchOption(this, 'log')}
113115
{renderSmallSwitchOption(this, 'inverted')}
116+
{renderSmallSwitchOption(this, 'empty')}
114117
{renderSmallSwitchOption(this, 'debug')}
115118
<Spindicator value={this._scrollPos} />
116119
</View>
@@ -120,7 +123,8 @@ class FlatListExample extends React.PureComponent<{}, $FlowFixMeState> {
120123
ItemSeparatorComponent={ItemSeparatorComponent}
121124
ListHeaderComponent={<HeaderComponent />}
122125
ListFooterComponent={FooterComponent}
123-
data={filteredData}
126+
ListEmptyComponent={ListEmptyComponent}
127+
data={this.state.empty ? [] : filteredData}
124128
debug={this.state.debug}
125129
disableVirtualization={!this.state.virtualized}
126130
getItemLayout={this.state.fixedHeight ?
@@ -210,6 +214,7 @@ const styles = StyleSheet.create({
210214
},
211215
list: {
212216
backgroundColor: 'white',
217+
flexGrow: 1,
213218
},
214219
options: {
215220
flexDirection: 'row',

RNTester/js/ListExampleShared.js

+16
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,16 @@ class HeaderComponent extends React.PureComponent<{}> {
117117
}
118118
}
119119

120+
class ListEmptyComponent extends React.PureComponent<{}> {
121+
render() {
122+
return (
123+
<View style={styles.listEmpty}>
124+
<Text>The list is empty :o</Text>
125+
</View>
126+
);
127+
}
128+
}
129+
120130
class SeparatorComponent extends React.PureComponent<{}> {
121131
render() {
122132
return <View style={styles.separator} />;
@@ -240,6 +250,11 @@ const styles = StyleSheet.create({
240250
headerFooterContainer: {
241251
backgroundColor: 'rgb(239, 239, 244)',
242252
},
253+
listEmpty: {
254+
alignItems: 'center',
255+
justifyContent: 'center',
256+
flexGrow: 1,
257+
},
243258
horizItem: {
244259
alignSelf: 'flex-start', // Necessary for touch highlight
245260
},
@@ -317,6 +332,7 @@ const styles = StyleSheet.create({
317332
module.exports = {
318333
FooterComponent,
319334
HeaderComponent,
335+
ListEmptyComponent,
320336
ItemComponent,
321337
ItemSeparatorComponent,
322338
PlainInput,

0 commit comments

Comments
 (0)