如何在使用Firestore的React中正确分页数据?

时间:2019-06-17 13:54:01

标签: reactjs firebase pagination google-cloud-firestore

当我开始使用Firebase时,我对博客网站:(。

我想我有点理解Google的文档,并且知道如何将分页转移到下一页。但是,我绝对不知道如何分页回到上一页。

基本上,我希望有一个简单的分页组件,其外观应类似于:<1 2 3 [...](您可以在其中使用箭头分页,然后向后分页)。

可以分页到下一页,但是当涉及到分页时,我找不到在纯React中做任何合适的教程。

我尝试使用startAt,endAt,endBefore等各种方法。但是结果是或出现错误,或者将我带回到了第一页(即使我位于第三或第四页)

我什至试图在数组中找到第一个对象并将其用作endBefore,但它再次导致了分页回到第一页。

这就是我的代码现在的外观(是的,我知道pageNext()和pagePrev()相同)

import React, { Component } from 'react'
import { withFirebase } from './Firebase'
import Post from './Post'

import '../scss/Post.scss'

class Posts extends Component {
    constructor(props) {
        super(props);
        this.state = {
            loading:false,
            posts:[],
            post_id:[],
            lastVisible:null,
            limit:2
        }

        this.handlePageNext = this.handlePageNext.bind(this);
    }
    componentDidMount() {
        let newPosts=[];
        let postsId=[];

        this.setState({ loading: true });

        this.props.firebase.posts()
        .orderBy('date', 'desc')
        .limit(2)
        .get().then(querySnapshot => {
            let lastVisible = querySnapshot.docs[querySnapshot.docs.length-1];
            this.setState({ lastVisible: lastVisible});

            querySnapshot.forEach(doc => {
                newPosts = newPosts.concat(doc.data());
                postsId = postsId.concat(doc.id);           
                this.setState({
                    posts:newPosts,
                    post_id:postsId,
                    loading:false
                });
            })
        })



    }

    handlePageNext() {
        let newPosts=[];
        let postsId=[];

        this.setState({ loading: true });

        this.props.firebase.posts()
        .orderBy('date', 'desc')
        .startAt(this.state.lastVisible)
        .limit(this.state.limit)
        .get().then(querySnapshot => {
            let lastVisible = querySnapshot.docs[querySnapshot.docs.length-1];

            this.setState({ lastVisible:lastVisible });
            querySnapshot.forEach(doc => {
                newPosts = newPosts.concat(doc.data());
                postsId = postsId.concat(doc.id);           
                this.setState({
                    posts:newPosts,
                    post_id:postsId,
                    loading:false
                });
            })
        })
    }

    handlePagePrev() {
        let newPosts=[];
        let postsId=[];

        this.setState({ loading: true });

        this.props.firebase.posts()
        .orderBy('date', 'desc')
        .startAt(this.state.lastVisible)
        .limit(this.state.limit)
        .get().then(querySnapshot => {
            let lastVisible = querySnapshot.docs[querySnapshot.docs.length-1];

            this.setState({ lastVisible:lastVisible});
            querySnapshot.forEach(doc => {
                newPosts = newPosts.concat(doc.data());
                postsId = postsId.concat(doc.id);           
                this.setState({
                    posts:newPosts,
                    post_id:postsId,
                    loading:false
                });
            })
        })
    }

    render() {
        return (
            <div className='posts'>
                <div className='row'>
                    {this.state.posts.map((post, i) => (
                        <Post 
                            key={i}
                            title={post.title}
                            author={post.author}
                            desc={post.desc}
                            text={post.text}
                            id={this.state.post_id[i]}
                            date={post.date}
                            imgURL={post.imgURL}/>
                    ))}

                    {this.state.loading && <p>Loading...</p>}
                    <button className='btn' onClick={() => this.handlePagePrev()}>&larr;</button>
                    <button className='btn' onClick={() => this.handlePageNext()}>></button>

                </div>

            </div>
        )
    }
}

export default withFirebase(Posts);

我想使用按钮(向左和向右箭头)进行简单的分页,但是我已经挣扎了3个小时,无法找到正确的解决方案。

2 个答案:

答案 0 :(得分:1)

Here是在reactjs中使用Firebase的标准分页。

答案 1 :(得分:1)

您必须保留“ lastVisible”并将其传递给startAfter()。我在下面编写了2个函数:

export const getMostRecentPostsFirstPage = (limit, specificUserId) => {
  if (!Number.isInteger(limit) || limit < 1) {
    throw new Error('limit must be a positive integer');
  }

  const collection = Firestore.collection('posts');
  let query = null;

  if (specificUserId) {
    query = collection
      .where('userId', '==', `${specificUserId}`)
      .orderBy('postedTimestamp', 'desc')
      .limit(limit);
  } else {
    query = collection.orderBy('postedTimestamp', 'desc').limit(limit);
  }

  return new Promise((resolve, reject) => {
    const posts = [];
    query
      .get()
      .then(snapshot => {
        const lastVisible = snapshot.docs[snapshot.docs.length - 1];
        snapshot.forEach(post => {
          posts.push(post.data());
        });
        const hasMore = posts.length == limit;
        resolve({ posts: posts, lastVisible: lastVisible, hasMore: hasMore });
      })
      .catch(error => reject(error));
  });
};
export const getMostRecentPostsNextPage = (lastVisible, limit, specificUserId) => {
  if (!lastVisible) {
    throw new Error('Need to provide lastVisible argument');
  }

  if (!Number.isInteger(limit) || limit < 1) {
    throw new Error('limit must be a positive integer');
  }

  const collection = Firestore.collection('posts');
  let query = null;

  if (specificUserId) {
    query = collection
      .where('userId', '==', `${specificUserId}`)
      .orderBy('postedTimestamp', 'desc')
      .startAfter(lastVisible)
      .limit(limit);
  } else {
    query = collection
      .orderBy('postedTimestamp', 'desc')
      .startAfter(lastVisible)
      .limit(limit);
  }

  return new Promise((resolve, reject) => {
    const posts = [];
    query
      .get()
      .then(snapshot => {
        const lastVisible = snapshot.docs[snapshot.docs.length - 1];
        snapshot.forEach(post => {
          posts.push(post.data());
        });
        const hasMore = posts.length == limit;
        resolve({ posts: posts, lastVisible: lastVisible, hasMore: hasMore });
      })
      .catch(error => reject(error));
  });
};

它使用redux-saga,但您明白了。

在第一个查询中,请勿调用“ startAfter()”,而在后续查询中执行,并且每次调用之间必须保存“ lastVisible”。