1

我正在使用 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);
4

0 回答 0