javascriptreactjsreact-nativereact-native-flatlistsafeareaview

React Native FlatList ListHeaderComponent wrapped in SafeAreaView doesn't respect the boundaries of SafeAreaView


Description

Hello, I'm pretty new to React Native and I was trying to render a FlatList inside a ScrollView and I got an error mentioning this application of FlatList inside ScrollView is not proper and it may cause some scroll disorientations. So, I searched for solutions to this problem and found out there's ListHeaderComponent property for FlatList to render everything else inside ScrollView. I accomplished implementing this solution to my screen but now It doesn't respect to boundaries of SafeAreaView which is pretty annoying, I don't want to add hard-coded margin/padding to the outer ScrollView/View component. It wouldn't be pretty.

Current Implementation

screens/Home.js:

import React from 'react';
import {
    View,
    ScrollView,
    StyleSheet,
    Dimensions,
    SafeAreaView
} from 'react-native';

import SearchBar from '../components/UI/SearchBar';
import CarouselSlider from '../components/UI/CarouselSlider';
import FeaturedProducts from '../components/UI/FeaturedProducts';
import RecommendedCategories from '../components/UI/RecommendedCategories';
import ProductList from '../components/UI/ProductList';
import { HeadingSecondary } from '../components/UI/Typography';

import CarouselSliderData from '../data/slider';
import MostSold from '../data/mostSold';
import Categories from '../data/categories';

const { width } = Dimensions.get('window');

const Home = props => {
    const HeaderPart = (
        <ScrollView>
            <View style={styles.sectionSlider}>
                <CarouselSlider
                    data={CarouselSliderData}
                    height={width*0.6}
                    width={width}
                    itemWidth={width - (width/5)}
                />
            </View>
            <View style={styles.sectionFeatured}>
                <HeadingSecondary>Featured Products</HeadingSecondary>
                <FeaturedProducts data={MostSold} />
            </View>
            <View style={styles.sectionRecommendedCategories}>
                <HeadingSecondary>Recommended Categories For You</HeadingSecondary>
                <RecommendedCategories data={Categories} />
            </View>
            <HeadingSecondary>Recommended Products For You</HeadingSecondary>
        </ScrollView>
    );

    return (
        <SafeAreaView style={styles.container}>
            <SearchBar />
            <View style={styles.sectionProducts}>
                <ProductList
                    data={MostSold}
                    numColumns={2}
                    key={'Products'}
                    ListHeaderComponent={HeaderPart}
                />
            </View>
        </SafeAreaView>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center'
    },
    sectionSlider: {
        height: width*0.6,
        marginBottom: 12
    }
});

export default Home;

components/UI/ProductList.js:

import React from 'react';
import {
    View,
    FlatList,
    StyleSheet,
    SafeAreaView
} from 'react-native';

import ProductItem from './ProductItem';

const ProductList = props => {
    return (
        <View style={styles.container}>
            <FlatList
                data={props.data}
                renderItem={itemData =>
                    <ProductItem {...itemData.item} />
                }
                {...props}
            />
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1
    }
});

export default ProductList;

Current Result Of Implementation

Current Result

What I Want to Accomplish

Aimed Result

Thanks in advance!


Solution

  • It seems like wrapping the FlatList with ListHeaderComponent/ListFooterComponent properties inside a View component is not correct. I have updated my code to below and it's solved.

    screens/Home.js

    ...
    const Home = props => {
        ...
        return (
            <SafeAreaView style={styles.container}>
                <SearchBar />
                <ProductList
                    data={MostSold}
                    numColumns={2}
                    key={'Products'}
                    ListHeaderComponent={HeaderPart}
                />
            </SafeAreaView>
        );
    };
    ...