我正在使用 Intersection Observer 来查看 div 元素是否在视口中,这实际上是页面的底部。在 useEffect 钩子中,我从 Firestore 获取博客并保存到状态,在我滚动到底部第二个获取功能运行后,它会获取另一个博客。我正在使用以前的博客和新博客设置博客状态,但是以前的博客不知何故是空数组。它只输出新的博客,旧的已经消失了。
getBlogs 正在从 Firestore 获取文档并使用获取的博客创建新数组。
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import BlogListItem from './BlogListItem';
import db from '../firebase/firebase';
import BlogFilters from './BlogFilters';
import loader from '../images/loader.gif';
import RecentFeed from './RecentFeed';
import BlogsContext from '../context/blogs-context';
let startDoc = null;
const getBlogs = docs => {
const blogs = [];
docs.forEach(doc => {
blogs.push({
id: doc.id,
...doc.data(),
});
});
startDoc = docs[docs.length - 1];
return blogs;
};
const firstFetchBlogs = async () => {
const data = await db.collection('blogs').orderBy('createdAt', 'desc').limit(5).get();
return getBlogs(data.docs);
};
const fetchBlogs = async () => {
const data = await db.collection('blogs').orderBy('createdAt', 'desc').startAfter(startDoc).limit(5).get();
return getBlogs(data.docs);
};
export const ReadBlogList = () => {
const [ blogs, setBlogs ] = useState([]);
const [ loading, setLoading ] = useState(true);
const [ smallLoading, setSmallLoading ] = useState(false);
const [ noMore, setNoMore ] = useState(false);
const scrollElement = React.useRef();
const paginateBlogs = () => {
setSmallLoading(true);
fetchBlogs()
.then(newBlogs => {
setBlogs([ ...blogs, ...newBlogs ]);
setSmallLoading(false);
})
.catch(() => {
setSmallLoading(false);
setNoMore(true);
});
};
const io = new IntersectionObserver(entries => {
const ratio = entries[0].intersectionRatio;
if (ratio > 0) {
paginateBlogs();
}
});
useEffect(() => {
let didCancel = false;
firstFetchBlogs().then(newBlogs => {
if (!didCancel) {
setBlogs(newBlogs);
setLoading(false);
io.observe(scrollElement.current);
}
});
return () => {
didCancel = true;
};
}, []);
return (
<div className="container read-blog-list">
<BlogFilters />
{loading && <img src={loader} alt="Loader" />}
{!loading && (
<BlogsContext.Provider value={{ blogs }}>
<div className="read-blog-list__content">
{blogs.length > 0 ? (
<div className="read-blog-list__blogs">
{blogs.map(blog => <BlogListItem to="read" key={blog.id} {...blog} />)}
<div ref={scrollElement} />
</div>
) : (
noMore && <p className="text-grey-darkest text-center text-xl">No more blogs</p>
)}
<RecentFeed />
{smallLoading && (
<div className="flex items-center justify-center">
<img className="w-12 h-12" src={loader} alt="Loader" />
</div>
)}
</div>
</BlogsContext.Provider>
)}
</div>
);
};
const mapStateToProps = state => ({
filters: state.filters,
});
export default connect(mapStateToProps)(ReadBlogList);