Adding new styling props to FlatList/VirtualizedList for ListHeaderComponent and ListFooterComponent

Summary:
We ran into a problem trying to style the optional prop `ListHeaderComponent` in the `FlatList` library component. Essentially we wanted to make `ListHeaderComponent` a flex item that filled all of the empty space in the list if there was any. Unfortunately the `ListHeaderComponent` is later wrapped in a `View` that blocked our styling. The `View` component was necessary as it added styling to handle inverting the `FlatList`. Similarly `ListFooterComponent` was handled the same way.

We came up the simple solution of adding two new optional props, `ListHeaderComponentStyle` and `ListFooterComponentStyle`, that are of type `ViewStyleProp` that allow users to pass in styling for `ListHeaderComponent` and `ListFooterComponent`.

With this change we were able to do something like the following to get the header component to fill all empty space in the `FlatList`.

```
<FlatList
    ...
    contentContainerStyle={{flexGrow: 1}}
    ListHeaderComponent={<View style={{flex: 1}} />}
    ListHeaderComponentStyle={{flexGrow: 1}}
    ...
/>
```
This solution will give users a lot more freedom when working with headers and footers.

Reviewed By: sahrens

Differential Revision: D8777038

fbshipit-source-id: f34116ce68548ea70223e639d0f84a099327f6b3
This commit is contained in:
Michael Ficaro 2018-07-12 13:36:50 -07:00 committed by Facebook Github Bot
parent 8ee60e9b0d
commit a2675ced4e
5 changed files with 30 additions and 10 deletions

View File

@ -18,7 +18,7 @@ const StyleSheet = require('StyleSheet');
const invariant = require('fbjs/lib/invariant'); const invariant = require('fbjs/lib/invariant');
import type {DangerouslyImpreciseStyleProp} from 'StyleSheet'; import type {DangerouslyImpreciseStyleProp, ViewStyleProp} from 'StyleSheet';
import type { import type {
ViewabilityConfig, ViewabilityConfig,
ViewToken, ViewToken,
@ -88,11 +88,19 @@ type OptionalProps<ItemT> = {
* a rendered element. * a rendered element.
*/ */
ListFooterComponent?: ?(React.ComponentType<any> | React.Element<any>), ListFooterComponent?: ?(React.ComponentType<any> | React.Element<any>),
/**
* Styling for internal View for ListFooterComponent
*/
ListFooterComponentStyle?: ViewStyleProp,
/** /**
* Rendered at the top of all the items. Can be a React Component Class, a render function, or * Rendered at the top of all the items. Can be a React Component Class, a render function, or
* a rendered element. * a rendered element.
*/ */
ListHeaderComponent?: ?(React.ComponentType<any> | React.Element<any>), ListHeaderComponent?: ?(React.ComponentType<any> | React.Element<any>),
/**
* Styling for internal View for ListHeaderComponent
*/
ListHeaderComponentStyle?: ViewStyleProp,
/** /**
* Optional custom style for multi-item rows generated when numColumns > 1. * Optional custom style for multi-item rows generated when numColumns > 1.
*/ */

View File

@ -31,7 +31,7 @@ const warning = require('fbjs/lib/warning');
const {computeWindowedRenderLimits} = require('VirtualizeUtils'); const {computeWindowedRenderLimits} = require('VirtualizeUtils');
import type {DangerouslyImpreciseStyleProp} from 'StyleSheet'; import type {DangerouslyImpreciseStyleProp, ViewStyleProp} from 'StyleSheet';
import type { import type {
ViewabilityConfig, ViewabilityConfig,
ViewToken, ViewToken,
@ -124,11 +124,19 @@ type OptionalProps = {
* a rendered element. * a rendered element.
*/ */
ListFooterComponent?: ?(React.ComponentType<any> | React.Element<any>), ListFooterComponent?: ?(React.ComponentType<any> | React.Element<any>),
/**
* Styling for internal View for ListFooterComponent
*/
ListFooterComponentStyle?: ViewStyleProp,
/** /**
* Rendered at the top of all the items. Can be a React Component Class, a render function, or * Rendered at the top of all the items. Can be a React Component Class, a render function, or
* a rendered element. * a rendered element.
*/ */
ListHeaderComponent?: ?(React.ComponentType<any> | React.Element<any>), ListHeaderComponent?: ?(React.ComponentType<any> | React.Element<any>),
/**
* Styling for internal View for ListHeaderComponent
*/
ListHeaderComponentStyle?: ViewStyleProp,
/** /**
* A unique identifier for this list. If there are multiple VirtualizedLists at the same level of * A unique identifier for this list. If there are multiple VirtualizedLists at the same level of
* nesting within another VirtualizedList, this key is necessary for virtualization to * nesting within another VirtualizedList, this key is necessary for virtualization to
@ -756,7 +764,12 @@ class VirtualizedList extends React.PureComponent<Props, State> {
<VirtualizedCellWrapper <VirtualizedCellWrapper
cellKey={this._getCellKey() + '-header'} cellKey={this._getCellKey() + '-header'}
key="$header"> key="$header">
<View onLayout={this._onLayoutHeader} style={inversionStyle}> <View
onLayout={this._onLayoutHeader}
style={StyleSheet.compose(
inversionStyle,
this.props.ListHeaderComponentStyle,
)}>
{ {
// $FlowFixMe - Typing ReactNativeComponent revealed errors // $FlowFixMe - Typing ReactNativeComponent revealed errors
element element
@ -892,7 +905,12 @@ class VirtualizedList extends React.PureComponent<Props, State> {
<VirtualizedCellWrapper <VirtualizedCellWrapper
cellKey={this._getCellKey() + '-footer'} cellKey={this._getCellKey() + '-footer'}
key="$footer"> key="$footer">
<View onLayout={this._onLayoutFooter} style={inversionStyle}> <View
onLayout={this._onLayoutFooter}
style={StyleSheet.compose(
inversionStyle,
this.props.ListFooterComponentStyle,
)}>
{ {
// $FlowFixMe - Typing ReactNativeComponent revealed errors // $FlowFixMe - Typing ReactNativeComponent revealed errors
element element

View File

@ -60,7 +60,6 @@ exports[`FlatList renders all the bells and whistles 1`] = `
<View> <View>
<View <View
onLayout={[Function]} onLayout={[Function]}
style={null}
> >
<header /> <header />
</View> </View>
@ -119,7 +118,6 @@ exports[`FlatList renders all the bells and whistles 1`] = `
</View> </View>
<View <View
onLayout={[Function]} onLayout={[Function]}
style={null}
> >
<footer /> <footer />
</View> </View>

View File

@ -341,7 +341,6 @@ exports[`SectionList renders all the bells and whistles 1`] = `
<View> <View>
<View <View
onLayout={[Function]} onLayout={[Function]}
style={null}
> >
<header <header
v="" v=""
@ -484,7 +483,6 @@ exports[`SectionList renders all the bells and whistles 1`] = `
</View> </View>
<View <View
onLayout={[Function]} onLayout={[Function]}
style={null}
> >
<footer <footer
v="" v=""

View File

@ -665,14 +665,12 @@ exports[`VirtualizedList renders empty list with empty component 1`] = `
<View> <View>
<View <View
onLayout={[Function]} onLayout={[Function]}
style={null}
> >
<header /> <header />
</View> </View>
<empty /> <empty />
<View <View
onLayout={[Function]} onLayout={[Function]}
style={null}
> >
<footer /> <footer />
</View> </View>