Permalink
Browse files

Adding new styling props to FlatList/VirtualizedList for ListHeaderCo…

…mponent 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
  • Loading branch information...
Michael Ficaro authored and facebook-github-bot committed Jul 12, 2018
1 parent 8ee60e9 commit a2675ced4efe0df7745bf38908efa41d4d7a9841
@@ -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.
*/
@@ -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
@@ -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>
@@ -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=""
@@ -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>

1 comment on commit a2675ce

@Noitidart

This comment has been minimized.

Show comment
Hide comment
@Noitidart

Noitidart Sep 12, 2018

I think better names for this prop would be ListHeaderComponentContainerStyle and ListFooterComponentContainerStyle (notice the added Container). Because we're stylling the contaienr view, and not the actual component. We should probably also document this in the docs, as we document the ScrollView container, as that has major repercussions on styling/layout.

Noitidart commented on a2675ce Sep 12, 2018

I think better names for this prop would be ListHeaderComponentContainerStyle and ListFooterComponentContainerStyle (notice the added Container). Because we're stylling the contaienr view, and not the actual component. We should probably also document this in the docs, as we document the ScrollView container, as that has major repercussions on styling/layout.

Please sign in to comment.