我正在使用Firebase-Cloud Firestore,目前我想对所有可用记录进行分页。我已经有记录列表了,剩下的就是一些分页了。我是Cloud Firestore的新手,因此感谢您提供任何清晰度。
我使用ReactJS查看了Firestore文档(https://firebase.google.com/docs/firestore/query-data/query-cursors#paginate_a_query)和示例,但是没有太多可用。
我理解例如:.startAt(0), .limit(10)
,但问题是如何使用render方法调用的该组件正确地分页。
import React, { Component } from 'react';
import Pagination from "react-js-pagination";
import firestore from "./Firebase";
export default class DataList extends Component {
constructor(props) {
super(props);
this.state = {
dbItems: [],
currentPage: 1,
itemsPerPage: 3,
totalItemCount: 1,
activePage: 15
}
this.handlePageChange = this.handlePageChange.bind(this);
}
handlePageChange(pageNumber) {
console.log(`active page is ${pageNumber}`);
this.setState({ activePage: pageNumber });
}
async getItems() {
const { currentPage, itemsPerPage } = this.state;
const startAt = currentPage * itemsPerPage - itemsPerPage;
const usersQuery = firestore.collection('Users').orderBy("email").startAt(startAt).limit(itemsPerPage)
const snapshot = await usersQuery.get()
const items = snapshot.docs.map(doc => doc.data())
return this.setState({
dbItems: items,
totalItemCount: firestore.collection('Users').get().then(res => console.log(res.size))
})
}
componentDidMount() {
this.getItems()
}
componentDidUpdate(prevProps, prevState) {
const isDifferentPage = this.state.currentPage !== prevState.currentPage
if (isDifferentPage) this.getItems()
}
render() {
return (
<div>
{this.state.dbItems.map((users, index) => {
return (
<p key={index}>
<b>First Name:</b> {users.firstname} <br />
<b>Email:</b> {users.email}
</p>
)
})
}
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={this.state.itemsPerPage}
totalItemsCount={this.state.totalItemCount}
pageRangeDisplayed={this.state.itemsPerPage}
onChange={this.handlePageChange}
/>
</div>
)
}
}
谢谢您的帮助!
答案 0 :(得分:4)
// Get Items.
async getItems() {
const {currentPage, itemsPerPage} = this.state
const startAt = currentPage * itemsPerPage - itemsPerPage
const query = firestore.collection('Users').startAt(startAt).limit(itemsPerPage)
const snapshot = await query.get()
const items = snapshot.docs.map(doc => doc.data())
return this.setState({dbItems: items})
}
// Did Mount.
componentDidMount() {
this.getItems()
}
// Did Update.
componentDidUpdate(prevProps, prevState) {
const isDifferentPage = this.state.currentPage !== prevState.currentPage
if (isDifferentPage) this.getItems()
}
答案 1 :(得分:3)
对Firestore和Firestore Pagination和ReactJS陌生的任何人都很难理解分页的工作方式或何时触发对Firestore中下一组文档的调用。像这样挣扎的任何人都可以尝试我的示例来提出一些想法并向前进行。(我使用React-Bootstrap来呈现UI元素)
01-安装软件包react-infinite-scroll-component
首先安装此软件包yarn add react-infinite-scroll-component
02-包含软件包
通过'import InfiniteScroll from 'react-infinite-scroll-component';'
导入将其包含到文件中
03-初始化状态
使用空列表数组初始化状态
this.state = {
list: [],
};
04-创建函数以获取第一组数据并使用安装了组件的组件进行初始化
//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-创建获取余额数据集的功能
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-渲染界面
<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>
答案 2 :(得分:0)
为此使用startAt()或startAfter()
firestore
.collection("Users")
.startAt(0)
.limit(10)
.get()
答案 3 :(得分:0)
//initial state
const [list, setList] = useState([]);
const [page, setPage] = useState(1);
//loading initial data
useEffect(() => {
const fetchData = async () => {
await firebase.firestore().collection('users')
.orderBy('created', 'desc') //order using firestore timestamp
.limit(5) //change limit value as your need
.onSnapshot(function(querySnapshot) {
var items = [];
querySnapshot.forEach(function(doc) {
items.push({ key: doc.id, ...doc.data() });
});
setList(items);
})
};
fetchData();
}, []);
加载初始数据后使用以下函数触发下一个按钮
//next button function
const showNext = ({ item }) => {
if(list.length === 0) {
//use this to show hide buttons if there is no records
} else {
const fetchNextData = async () => {
await firebase.firestore().collection('users')
.orderBy('created', 'desc') //order using firestore timestamp
.limit(5) //change limit value as your need
.startAfter(item.created) //we pass props item's first created timestamp to do start after you can change as per your wish
.onSnapshot(function(querySnapshot) {
const items = [];
querySnapshot.forEach(function(doc) {
items.push({ key: doc.id, ...doc.data() });
});
setList(items);
setPage(page + 1) //in case you like to show current page number you can use this
})
};
fetchNextData();
}
};
然后上一个按钮功能
//previous button function
const showPrevious = ({item}) => {
const fetchPreviousData = async () => {
await firebase.firestore().collection('users')
.orderBy('created', 'desc')
.endBefore(item.created) //this is important when we go back
.limitToLast(5) //this is important when we go back
.onSnapshot(function(querySnapshot) {
const items = [];
querySnapshot.forEach(function(doc) {
items.push({ key: doc.id, ...doc.data() });
});
setList(items);
setPage(page - 1)
})
};
fetchPreviousData();
};
最后创建列表视图和两个这样的按钮
{
//list doc's here this will come inside return (place this code inside table)
list.map((doc) => (
<tr key={doc.key}>
<td>{ doc.name }</td>
<td>{ doc.age }</td>
<td>{ doc.note }</td>
</tr>
))
}
{
//show previous button only when we have items
//pass first item to showPrevious function
page === 1 ? '' :
<Button onClick={() => showPrevious({ item: list[0] }) }>Previous</Button>
}
{
//show next button only when we have items
//pass last item to showNext function
list.length < 5 ? '' :
<Button onClick={() => showNext({ item: list[list.length - 1] })}>Next</Button>
}
就是检查我的代码注释,您可以根据需要进行更改。这就是使用 Firebase FireStore 进行分页时会发生的情况。您可以根据需要使用创建自定义钩子来重用这些组件。
希望这可以帮助某人所以我做了一个要点检查it here