Add a button "see more" in FlatList?

Viewed 3688

I use flatList to make a list of elements. I would like to show 15 elements and then add a button "see more" to show the next 15 etc. I was about tu use this tutorial : https://aboutreact.com/react-native-flatlist-pagination-to-load-more-data-dynamically-infinite-list/ But I don't need to use fetch, I already have set up the data (state.listData) and in fact, I'm a little lost on how to adapt it...

I thought that maybe anyone could help me a little. Thanks a lot

   this.state = {
      selectedId: '',
      setSelectedId:'',
      listData:''
    }
  };


  renderItem = ({ item }) => {
    const backgroundColor = item.id === this.selectedId ? "transparent" : "fff";

    return (
      <View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
        <Item
          item={item}
          onPress={() => this.props.navigation.navigate('UpdateTripsForm')}
          style={{ backgroundColor }}
        />
        <Image source={require("../../assets/images/arrow.png")} style={{width: 15, height:15, justifyContent: 'center'}}/>
      </View>
    );
  };

  initListData = async () => {
    let list = await getFlights(0);

    if (list) {
      this.setState({
        listData: list
      });
    }
  };

render() {
    return (
            <SafeAreaView style={styles.container}>
              <FlatList
                data={this.state.listData}
                renderItem={this.renderItem}
                maxToRenderPerBatch={15}
                keyExtractor={(item) => item.id}
                extraData={this.selectedId}
              />
              <TouchableOpacity
                style={styles.touchable2}
                onPress={() => this.props.navigation.goBack()}
              >
                <View style={styles.view2}>
                  <Text style={styles.textimg2}>
                    {i18n.t("tripsform.action.back")}
                  </Text>
                </View>
                <Image
                  source={require("../../assets/images/btn-background.png")}
                  style={styles.tripsimg2}
                />
              </TouchableOpacity>
            </SafeAreaView>
    );
  };
}

I just tried this thanks to @Pramod 's answer :

const Item = ({ item, onPress, style }) => (
  <TouchableOpacity onPress={onPress} style={[styles.flightsListitem, style]}>
    <Text style={styles.h4}>{item.id}</Text>
  </TouchableOpacity>
);

export default class FlightsList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedId: '',
      setSelectedId:'',
      listData:'',
      page:1,
      perPage:2,
      loadMoreVisible:true,
      displayArray:[]
    }
  };


  renderItem = ({ item }) => {
    const backgroundColor = item.id === this.selectedId ? "transparent" : "fff";

    return (
      <View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
        <Item
          item={item}
          onPress={() => this.props.navigation.navigate('UpdateTripsForm')}
          style={{ backgroundColor }}
        />
        <Image source={require("../../assets/images/arrow.png")} style={{width: 15, height:15, justifyContent: 'center'}}/>
      </View>
    );
  };

  initListData = async () => {
    let list = await getFlights(0);

    if (list) {
      this.setState({
        listData: list
      });
    }
  };

  componentDidMount(){
      this.setNewData()
      // console.log(tempArray)
    }

    setNewData(){
      var tempArray=[]
      if(this.state.listData.length == this.state.displayArray.length){
        this.setState({
          loadMoreVisible:false
        })
      }else{
         for(var i=0; i<(this.state.page*this.state.perPage); i++){
        tempArray.push(this.state.listData)
        }
        this.setState({
          displayArray: tempArray,
          loadMoreVisible:true
        })
      }
    }

  loadMore(){
    this.setState({
      page: this.state.page+1
    },()=>{
      this.setNewData()
    })
  }

  async UNSAFE_componentWillMount() {
    this.initListData();
  }

  render() {
    return (
      <ImageBackground
        source={require("../../assets/images/background.jpg")}
        style={styles.backgroundImage}
      >
        <Header
          backgroundImage={require("../../assets/images/bg-header.png")}
          backgroundImageStyle={{
            resizeMode: "stretch",
          }}
          centerComponent={{
            text: i18n.t("mytrips.title"),
            style: styles.headerComponentStyle,
          }}
          containerStyle={[styles.headerContainerStyle, { marginBottom: 0 }]}
          statusBarProps={{ barStyle: "light-content" }}
        />
          <SafeAreaView style={styles.container}>
              <FlatList
                data={this.state.displayArray}
                renderItem={this.renderItem}
                keyExtractor={(item) => item.id}
                extraData={this.selectedId}
              />
            {this.state.loadMoreVisible == true?
                <Button style={{width:'100%', height:10, backgroundColor:'green', justifyContent:'center', alignItems:'center'}}
                        title = 'load more'
                        onPress={()=>{this.loadMore()}}>
                </Button>:null}
              <TouchableOpacity
                style={styles.touchable2}
                onPress={() => this.props.navigation.goBack()}
              >
                <View style={styles.view2}>
                  <Text style={styles.textimg2}>
                    {i18n.t("tripsform.action.back")}
                  </Text>
                </View>
                <Image
                  source={require("../../assets/images/btn-background.png")}
                  style={styles.tripsimg2}
                />
              </TouchableOpacity>
            </SafeAreaView>
      </ImageBackground>
    );
  };
}

the flatlist is not displayed : I get : enter image description here

2 Answers
  1. Set data in state (already done ==> this.state.listData)
  2. Set counter in state (initialize with 1)
  3. Set 15 first elements in state (you can name it "renderedData" or something like that) and then increase cuonter to 1
  4. Add a function that increases the "renderedData" by 15 items by increasing the counter by one
  5. Add Footer component to the list which will call the function you created in stage 3



To take only 15( or 30/45/60 etc..) items from the list you can do something like this:

this.setState({ renderedItem: listData.slice(0, counter*15) })

You can user pagination method with per page limit so that you can have granular control

  1. Load the array per page when component mount
  2. On every click increase the per page and based on per page update data of your flat list
  3. And also put a flag which will check when the data has ended which will help to hide the load more button when data ends

Working example: https://snack.expo.io/@msbot01/suspicious-orange

 import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  SafeAreaView,
  SectionList,
  Switch,
  FlatList
} from 'react-native';
import Constants from 'expo-constants';
import Icon from 'react-native-vector-icons/FontAwesome';

import AwesomeIcon from 'react-native-vector-icons/FontAwesome';

// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
 

export default class App extends Component<Props> {
  constructor(props) {
    super(props);
    this.state = {
      page:1,
      perPage:2,
      loadMoreVisible:true,
      DATA: [{
          id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
          title: 'First Item',
        },
        {
          id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
          title: 'Second Item',
        },
        {
          id: '58694a0f-3da1-471f-bd96-145571e29d72',
          title: 'Third Item',
        },
        {
          id: '58694a0f-3da1-471f-bd96-145571e29d72',
          title: 'fourth Item',
        },
        {
          id: '58694a0f-3da1-471f-bd96-145571e29d72',
          title: 'fifth Item',
        },
        {
          id: '58694a0f-3da1-471f-bd96-145571e29sd72',
          title: 'sixth Item',
        },
        {
          id: '58694a0f-3da1-471f-bd96-145571e29dr72',
          title: 'seventh Item',
        },
        {
          id: '58694a0f-3da1-471f-bd96-145571e29d7w2',
          title: 'Eight Item',
        },
        {
          id: '58694a0f-3da1-471f-bd96-145571e29ad72',
          title: 'Nineth Item',
        },
        {
          id: '58694a0f-3da1-471f-bd96-14557d1e29d72',
          title: 'Tenth Item',
        }],
    displayArray:[]
  } 
 
  }

  componentDidMount(){
    
    this.setNewData()
    // console.log(tempArray) 
  }

  setNewData(){ 
    var tempArray=[]
    if(this.state.DATA.length == this.state.displayArray.length){
      this.setState({
        loadMoreVisible:false
      })
    }else{
       for(var i=0; i<(this.state.page*this.state.perPage); i++){
      tempArray.push(this.state.DATA[i])
      }
      this.setState({
        displayArray: tempArray,
        loadMoreVisible:true
      })
    }

   
  }

  loadMore(){
    this.setState({
      page: this.state.page+1
    },()=>{
      this.setNewData()
    })
  }
  

  render() {
    return (
      <View style={{ flex: 1 }}>
        <FlatList
        data={this.state.displayArray}
        renderItem={({item})=> 
          <View style={{flexDirection:'row'}}>
            <Text style={{fontSize:20}}>{item.title} </Text>
          </View>
        }
        keyExtractor={item => item.id}
      />
      {this.state.loadMoreVisible == true?

      
      <View style={{width:'100%', height:10, backgroundColor:'green', justifyContent:'center', alignItems:'center'}} onClick={()=>{this.loadMore()}}>Load more</View>:null
      }
      </View>
    );
  }
}
Related