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');
import type {DangerouslyImpreciseStyleProp} from 'StyleSheet';
import type {DangerouslyImpreciseStyleProp, ViewStyleProp} from 'StyleSheet';
import type {
ViewabilityConfig,
ViewToken,
@ -88,11 +88,19 @@ type OptionalProps<ItemT> = {
* a rendered element.
*/
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
* a rendered element.
*/
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.
*/

View File

@ -31,7 +31,7 @@ const warning = require('fbjs/lib/warning');
const {computeWindowedRenderLimits} = require('VirtualizeUtils');
import type {DangerouslyImpreciseStyleProp} from 'StyleSheet';
import type {DangerouslyImpreciseStyleProp, ViewStyleProp} from 'StyleSheet';
import type {
ViewabilityConfig,
ViewToken,
@ -124,11 +124,19 @@ type OptionalProps = {
* a rendered element.
*/
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
* a rendered element.
*/
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
* nesting within another VirtualizedList, this key is necessary for virtualization to
@ -756,7 +764,12 @@ class VirtualizedList extends React.PureComponent<Props, State> {
<VirtualizedCellWrapper
cellKey={this._getCellKey() + '-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
element
@ -892,7 +905,12 @@ class VirtualizedList extends React.PureComponent<Props, State> {
<VirtualizedCellWrapper
cellKey={this._getCellKey() + '-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
element

View File

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

View File

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

View File

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