【问题标题】:How to Implement Infinite Scroll in Next JS SSG?Next JS SSG如何实现无限滚动?
【发布时间】:2020-11-09 15:52:54
【问题描述】:

我按照 Next Js 文档和 Using Typescript 创建了一个降价博客。为了获取博客文章列表,我使用了getStaticProps 作为docs 的建议。我尝试了一些 npm 包,它不起作用,或者我不知道如何完美设置。

如果有好的插件自定义钩子,请告诉我如何在Next Js静态站点生成中添加无限滚动功能。

此 GitHub 存储库中提供了项目源代码:https://github.com/vercel/next-learn-starter/blob/master/typescript-final/pages/index.tsx

【问题讨论】:

    标签: reactjs typescript next.js


    【解决方案1】:

    我做了一些研究并创建了自己的 react 钩子来在 Next JS 中实现无限滚动。所以,我正在回答我的问题。

    如果有人有更好的方法,请不要忘记在这里分享。

    我找到了两种工作方法。第一个使用innerHeightscrollTopoffsetHeight 值完成。它工作得很好,但不知何故,我觉得这不是正确的方法。如果我错了,请纠正我。

    第二种方法是通过Intersection Observer API异步观察目标元素的交集变化。首先,我创建了一个分页自定义反应挂钩来限制我的博客文章,然后我使用 IntersectionObserver 来获取下一页的博客文章。

    usePagination.tsx:

    import { useState } from "react";
    
    function usePagination(data, itemsPerPage: number) {
      const [currentPage, setCurrentPage] = useState(1);
    
      const maxPage = Math.ceil(data.length / itemsPerPage);
    
      function currentData() {
        const begin = (currentPage - 1) * itemsPerPage;
        const end = begin + itemsPerPage;
        return data.slice(null, end);
      }
    
      function next() {
        setCurrentPage((currentPage) => Math.min(currentPage + 1, maxPage));
      }
    
      return { next, currentData, currentPage, maxPage };
    }
    
    export default usePagination;
    

    索引.tsx:

    import { GetStaticProps } from "next";
    import { getSortedPostsData } from "../lib/posts";
    import Layout from "../components/layout";
    import usePagination from "../lib/Hooks/usePagination";
    import { useRef, useState, useEffect } from "react";
    
    export default function Home({
      allPostsData,
    }: {
      allPostsData: {
        id: string;
        title: string;
        date: string;
        cover: string;
      }[];
    }) {
      const { next, currentPage, currentData, maxPage } = usePagination(
        allPostsData,
        8
      );
      const currentPosts = currentData();
      const [element, setElement] = useState(null);
    
      const observer = useRef<IntersectionObserver>();
      const prevY = useRef(0);
      useEffect(() => {
        observer.current = new IntersectionObserver(
          (entries) => {
            const firstEntry = entries[0];
            const y = firstEntry.boundingClientRect.y;
    
            if (prevY.current > y) {
              next();
            }
            prevY.current = y;
          },
          { threshold: 0.5 }
        );
      }, []);
    
      useEffect(() => {
        const currentElement = element;
        const currentObserver = observer.current;
    
        if (currentElement) {
          currentObserver.observe(currentElement);
        }
    
        return () => {
          if (currentElement) {
            currentObserver.unobserve(currentElement);
          }
        };
      }, [element]);
      return (
        <Layout>
    
          <article className="w-full mt-12 flex flex-wrap items-center justify-center">
            {currentPosts &&
              currentPosts.map(({ id, title, date, cover }) => (
                <div key={id} // ......
                </div>
              ))}
          </article>
          {currentPage !== maxPage ? (
            <h1 ref={setElement}>Loading Posts...</h1>
          ) : (
            <h1>No more posts available...</h1>
          )}
        </Layout>
      );
    }
    
    export const getStaticProps: GetStaticProps = async () => {
      const allPostsData = getSortedPostsData();
    
      return {
        props: {
          allPostsData,
        },
      };
    };
    

    【讨论】:

      猜你喜欢
      • 2017-08-29
      • 1970-01-01
      • 2022-06-16
      • 1970-01-01
      • 2017-05-02
      • 1970-01-01
      • 2016-03-27
      • 2019-09-23
      • 2015-05-18
      相关资源
      最近更新 更多