How to paginate Cloud Firestore data with ReactJs

Anyone new to Firestore and Firestore Pagination with ReactJS that would be kinda confusing to understand how Pagination will work or when to trigger call to next set of documents in firestore. anyone struggle like this try my example to make some ideas and process ahead.(Im using React-Bootstrap to render UI Elements)

01 - Install Package react-infinite-scroll-component

First Install this package yarn add react-infinite-scroll-component

02 - Include Package

Include it to your file by 'import InfiniteScroll from 'react-infinite-scroll-component';' importing it

03 - Init State

initiate state with empty list array

this.state = {
    list: [],
};

04 - Create Function to get first set of data and initiate it with component did mount

//component did mount will fetch first data from firestore 
componentDidMount(){
    this.getUsers()
}

getUsers(){
  let set = this
  //initiate first set
  var first = set.ref.collection("users").limit(12);
  first.get().then(function (documentSnapshots) {
    // Get the last visible document
    var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length-1];
    //initiate local list 
    const list = [];
    documentSnapshots.forEach(function(doc) {
        //im fetching only name and avatar url you can get any data 
        //from your firestore as you like
        const { name, avatar_full_url } = doc.data();
        //pushing it to local array
        list.push({ key: doc.id, name, avatar_full_url });
    });
        //set state with updated array of data 
        //also save last fetched data in state
        set.setState({ list, last: lastVisible });
    });
}

05 - Create function to get balance data set

fetchMoreData = () => {
  let set = this
  //get last state we added from getUsers()
  let last = this.state.last
  var next = set.ref.collection("users").startAfter(last).limit(12);
  next.get().then(function (documentSnapshots) {
  // Get the last visible document
  var lastVisible = documentSnapshots.docs[documentSnapshots.docs.length-1];
  const list = [];
  documentSnapshots.forEach(function(doc) {
    //im fetching only name and avatar url you can get any data 
    //from your firestore as you like
    const { name, avatar_full_url } = doc.data();
    list.push({ key: doc.id, name, avatar_full_url });
  });
  //set state with updated array of data 
  //also save last fetched data in state
  let updated_list = set.state.list.concat(list);
  set.setState({ list: updated_list, last: lastVisible });
  });
};

06 - Render UI

<InfiniteScroll 
  dataLength={this.state.list.length}
  next={this.fetchMoreData}
  hasMore={true}
  loader={<span className="text-secondary">loading</span>}>
    <Row className="mt-3">
      { this.state.list.map((single, index) => (
      <Col lg={4} key={ index }>
        <div>
          <Image src={ single.avatar_full_url }roundedCircle width="100" />
          <h2>{ single.name }</h2>
        </div>
      </Col>
      ))}
    </Row>  
</InfiniteScroll>

Pagination can be achieved using startAt()

// Get Items.
async fetchUsers = () => {

  // State.
  const {users, usersPerPage} = this.state

  // Last Visible.
  const lastVisible = users && users.docs[users.docs.length - 1]

  // Query.
  const query = firestore.collection('Users')
    .orderBy('email')
    .startAfter(lastVisible)
    .limit(usersPerPage)

  // Users.
  const users = await query.get()

  // ..
  return this.setState({users})

}

// Did Mount.
componentDidMount() {
  this.fetchUsers()
}

// Did Update.
componentDidUpdate(prevProps, prevState) {
  const isDifferentPage = this.state.currentPage !== prevState.currentPage
  if (isDifferentPage) this.fetchUsers()
}