”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 在 React 中构建无限滚动组件

在 React 中构建无限滚动组件

发布于2024-11-06
浏览:153

介绍

我们在应用程序和网页中看到无限滚动,尤其是希望我们滚动的社交媒体。虽然无意识地滚动不好,但构建自己的无限滚动是很棒的。作为开发人员,我们应该尝试重新创建我们在网上冲浪时看到的组件。它可以挑战您在实现某些组件时了解更多信息并跳出框框进行思考。

此外,如果您希望在应用程序中实现无限滚动,那么您可以按照指南创建自己的滚动。您可以添加自己的代码来改善滚动的行为。

在本文中,我们将从头开始构建一个无限滚动组件。它将涵盖以下主题:

  • 环境设置
  • 构建组件
  • 添加 CSS
  • 优化无限滚动

现在,让我们开始吧。

环境设置

我们将使用 CRA 创建基本的 React 应用程序。您可以运行以下命令来做到这一点:

    npx create-react-app infinite-scroll

如果您想使用 Vite 或 NextJS 也可以。除了细微的变化外,其他内容将保持不变。

注意:要运行此命令,您需要预先安装 NodeJS。 另外,从 CRA 中删除一些不必要的样板代码。

我们将需要一个依赖项来从 API 获取数据。设置好React后,我们就可以通过以下命令安装axios了:

    npm install axios

现在,我们准备创建组件了。

应用程序组件

我们将构建一个组件,从 Tmdb API 获取流行电影数据。您可以从他们的网站免费获取他们的 API 密钥。让我们首先构建他们获取数据的位置,然后添加无限滚动功能。

这是应用程序组件的代码:

App.js

    import "./App.css";
    import { useState, useEffect } from "react";
    import axios from "axios";
    import { MovieCard } from "./MovieCard";

    function App() {
      const [page, setPage] = useState(1); // for number of page in tmdb 
      const [data, setData] = useState([]); // storing the fetched data
      const [loading, setLoading] = useState(false); // for setting loading state

      // fetching and stroring the data in the state
      const fetchMovie = async () => {
        const URL = `https://api.themoviedb.org/3/movie/popular?language=en-US&page=${page}`;
        const data = await axios.get(URL, {
          headers: {
            Authorization:
              "Bearer API KEY",
            Accept: "application/json",
          },
        });
        setData((prevData) => [...prevData, ...data.data.results]); // we are going to add the new data to current data.
        setLoading(false);
      };

      // useEffecte for invoking the function at the start
      useEffect(() => {
        fetchMovie();
      }, [page]);

      return (
        
Popular movies according to Tmdb
{data.length > 1 && data.map((item) => { return ( ); })} {loading &&

Loading....

}
); } export default App;

您几乎可以理解代码,我们在其中获取数据并将其作为道具传递到 MovieCard 组件中。

创建一个 MovieCard.js 组件来显示每部电影的信息。

MoveCard.js

    import React from "react";

    export const MovieCard = ({ title, description, imageURL, rating }) => {

      const imagePath = `https://image.tmdb.org/t/p/w500${imageURL}`; // poster image path URL 

      return (
        
在 React 中构建无限滚动组件

{title}

{description}

{rating.toFixed(1)}⭐

); };

这是应用程序的 CSS:

App.css

    .App {
      text-align: center;
    }

    .App-header {
      background-color: #282c34;
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding-top: 1em;
      font-size: calc(10px   2vmin);
      color: white;
    }

    .movieCardContainer{
      margin-top: 1em;
      display: flex;
      flex-direction: column;
      gap: 1em;
      width: 60%;
      max-width: 800px;
    }

    .movieCard{
      display: flex;
    }

    .movieInfo{
      margin-left: 1em;
      text-align: left;
    }

    p{
      font-size: 18px;
    }

无限滚动

现在,让我们首先了解如何构建无限滚动。为此,我们将查看滚动条的位置。当滚动条位置正好位于页面末尾上方时,我们将把加载状态设置为true。

我们将有另一个 useEffect ,它会将页面状态增加 1。一旦更新页码,将触发将该页面作为依赖项的初始 useEffect。这将调用 fetchMovie() 函数来获取数据。

将事件监听器添加到滚动

首先,我们将添加甚至监听以了解滚动条位置何时更改。

    window.addEventListener("scroll", handleScroll);

处理滚动

当滚动发生时,我们将检查滚动条的当前位置是否位于网页底部的正上方(即总垂直滚动区域)。如果是,那么我们将加载状态更改为 true。

    const handleScroll = () => {
      if (document.body.scrollHeight - 300 



  • scrollHeight :该属性返回内容的总高度,包括屏幕上不可见的部分。因此,它将是总的可滚动区域。
  • scrollY:返回文档从顶部垂直滚动的像素数的属性。所以这将是已滚动的区域。
  • innerHeight:返回浏览器Windows内容区域高度的属性。它将是滚动条的宽度。它被添加到scrollY,以便当我们到达内容时而不是当我们传递内容时发生获取。 ## 使用效果

成功更改加载状态后,我们可以实现 useEffect 来增加页码。这样,就可以获取电影数据了。

    useEffect(() => {
      if (loading == true) {
        setPage((prevPage) => prevPage   1);
      }
    }, [loading]);

    // other useEffect that we already implemented

    useEffect(() => {
      fetchMovie();
    }, [page]);

优化事件监听器

由于scroll在滚动时会多次触发handleScroll,因此会导致多次不必要的函数调用。我们可以为函数添加去抖功能,以便在调用函数之前需要一些时间。

    // debounce function
    function debounce(func, delay) {
      let timeoutId;
      return function (...args) {
        if (timeoutId) {
          clearTimeout(timeoutId);
        }
        timeoutId = setTimeout(() => {
          func(...args);
        }, delay);
      };
    }

    // adding debounce to the eventListner
    window.addEventListener("scroll", debounce(handleScroll, 500));

这是App.js的完整代码:

    import "./App.css";
    import { useState, useEffect } from "react";
    import axios from "axios";
    import { MovieCard } from "./MovieCard";

    function App() {
      const [page, setPage] = useState(1);
      const [data, setData] = useState([]);
      const [loading, setLoading] = useState(false);
      const fetchMovie = async () => {

        const URL = `https://api.themoviedb.org/3/movie/popular?language=en-US&page=${page}`;
        const data = await axios.get(URL, {
          headers: {
            Authorization:
              "Bearer API KEY",
            Accept: "application/json",
          },
        });
        setData((prevData) => [...prevData, ...data.data.results]);
        setLoading(false);
      };
      useEffect(() => {
        fetchMovie();
      }, [page]);

      const handleScroll = () => {
        if (
          document.body.scrollHeight - 300  {
            func(...args);
          }, delay);
        };
      }

      window.addEventListener("scroll", debounce(handleScroll, 500));

      useEffect(() => {
        if (loading == true) {
          setPage((prevPage) => prevPage   1);
        }
      }, [loading]);

      return (
        
Popular movies according to Tmdb
{data.length > 1 && data.map((item) => { return ( ); })} {loading &&

Loading....

}
); } export default App;

这是演示应用程序工作原理的 GIF。

Building an Infinite Scroll Component in React

结论

在 React 中构建无限滚动组件可能是一次非常有益的体验。它不仅可以增强您对滚动工作原理的理解,还可以教您有关状态管理、事件侦听器和去抖等优化技术的知识。通过遵循本指南,您现在拥有基本的无限滚动设置,您可以根据需要进行自定义和改进。

无论您是显示电影数据、博客文章还是任何其他内容,此组件都可以作为坚实的基础。请记住,关键是通过仔细管理用户滚动时获取数据的时间和方式来确保流畅的用户体验。快乐编码!

版本声明 本文转载于:https://dev.to/surajondev/building-an-infinite-scroll-component-in-react-1ljb?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-04-30
  • 使用原生JavaScript触发ASP.NET异步回发:\_\_doPostBack()方法详解
    使用原生JavaScript触发ASP.NET异步回发:\_\_doPostBack()方法详解
    在Vanilla JavaScript 中使用__dopostback(&& &&&&)在trigger asynchronous后背是ASP.NET开发的基本方面。此JavaScript函数在促进无缝用户与Web应用程序的无缝交互中起着至关重要的作用。事件:一个可选参数,可用于传递其他信息以及发...
    编程 发布于2025-04-30
  • 为什么使用固定定位时,为什么具有100%网格板柱的网格超越身体?
    为什么使用固定定位时,为什么具有100%网格板柱的网格超越身体?
    网格超过身体,用100%grid-template-columns 为什么在grid-template-colms中具有100%的显示器,当位置设置为设置的位置时,grid-template-colly修复了?问题: 考虑以下CSS和html: class =“ snippet-code”> g...
    编程 发布于2025-04-30
  • 如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    postgresql:为每个唯一标识符在postgresql中提取最后一行,您可能需要遇到与数据集合中每个不同标识的信息相关的信息。考虑以下数据:[ 1 2014-02-01 kjkj 在数据集中的每个唯一ID中检索最后一行的信息,您可以在操作员上使用Postgres的有效效率: id dat...
    编程 发布于2025-04-30
  • 找到最大计数时,如何解决mySQL中的“组函数\”错误的“无效使用”?
    找到最大计数时,如何解决mySQL中的“组函数\”错误的“无效使用”?
    如何在mySQL中使用mySql 检索最大计数,您可能会遇到一个问题,您可能会在尝试使用以下命令:理解错误正确找到由名称列分组的值的最大计数,请使用以下修改后的查询: 计数(*)为c 来自EMP1 按名称组 c desc订购 限制1 查询说明 select语句提取名称列和每个名称...
    编程 发布于2025-04-30
  • 我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    将我的加密库从mcrypt升级到openssl 问题:是否可以将我的加密库从McRypt升级到OpenSSL?如果是这样,如何?答案:是的,可以将您的Encryption库从McRypt升级到OpenSSL。可以使用openssl。附加说明: [openssl_decrypt()函数要求iv参...
    编程 发布于2025-04-30
  • ASP.NET Core Web API中如何实现跨域资源共享(CORS)?
    ASP.NET Core Web API中如何实现跨域资源共享(CORS)?
    ASP.NET Core Web API 中启用 CORS:完整指南 跨源资源共享 (CORS) 是一种机制,允许 Web 浏览器进行跨源 HTTP 请求,通常针对与浏览器当前来源不同的域。启用 CORS 对于确保前端应用程序和托管在不同域或端口上的后端 Web API 之间的无缝通信至关重要。 ...
    编程 发布于2025-04-30
  • 如何构建带淡入淡出或滑动效果的jQuery图像滑块?
    如何构建带淡入淡出或滑动效果的jQuery图像滑块?
    创建一个简单的jQuery映像滑块,使用不透明度或滑动效果 jquery basics 在继续之前,重要的是要了解两个关键的jquery函数:eq() selects an element based on its index value.Slider EffectsThis slider sup...
    编程 发布于2025-04-30
  • Java中Lambda表达式为何需要“final”或“有效final”变量?
    Java中Lambda表达式为何需要“final”或“有效final”变量?
    Lambda Expressions Require "Final" or "Effectively Final" VariablesThe error message "Variable used in lambda expression shou...
    编程 发布于2025-04-30
  • 如何使用FormData()处理多个文件上传?
    如何使用FormData()处理多个文件上传?
    )处理多个文件输入时,通常需要处理多个文件上传时,通常是必要的。 The fd.append("fileToUpload[]", files[x]); method can be used for this purpose, allowing you to send multi...
    编程 发布于2025-04-30
  • 如何在其容器中为DIV创建平滑的左右CSS动画?
    如何在其容器中为DIV创建平滑的左右CSS动画?
    通用CSS动画,用于左右运动 ,我们将探索创建一个通用的CSS动画,以向左和右移动DIV,从而到达其容器的边缘。该动画可以应用于具有绝对定位的任何div,无论其未知长度如何。问题:使用左直接导致瞬时消失 更加流畅的解决方案:混合转换和左 [并实现平稳的,线性的运动,我们介绍了线性的转换。这...
    编程 发布于2025-04-30
  • PHP SimpleXML解析带命名空间冒号的XML方法
    PHP SimpleXML解析带命名空间冒号的XML方法
    在php 很少,请使用该限制很大,很少有很高。例如:这种技术可确保可以通过遍历XML树和使用儿童()方法()方法的XML树和切换名称空间来访问名称空间内的元素。
    编程 发布于2025-04-30
  • MySQL中字符串作为主键对性能影响大吗?
    MySQL中字符串作为主键对性能影响大吗?
    MySQL数据库中使用字符串作为主键的性能影响 在创建数据库时,主键是至关重要的组成部分,它唯一标识每一行数据,对数据完整性和查询效率起着重要作用。虽然整数由于其数值特性而通常用作主键,但在某些情况下,字符串可能更合适。 性能影响 从技术上讲,字符串可以在MySQL数据库中用作主键。但是,值得考虑...
    编程 发布于2025-04-30
  • eval()vs. ast.literal_eval():对于用户输入,哪个Python函数更安全?
    eval()vs. ast.literal_eval():对于用户输入,哪个Python函数更安全?
    称量()和ast.literal_eval()中的Python Security 在使用用户输入时,必须优先确保安全性。强大的Python功能Eval()通常是作为潜在解决方案而出现的,但担心其潜在风险。 This article delves into the differences betwee...
    编程 发布于2025-04-30
  • 您如何在Laravel Blade模板中定义变量?
    您如何在Laravel Blade模板中定义变量?
    在Laravel Blade模板中使用Elegance 在blade模板中如何分配变量对于存储以后使用的数据至关重要。在使用“ {{}}”分配变量的同时,它可能并不总是最优雅的解决方案。幸运的是,Blade通过@php Directive提供了更优雅的方法: $ old_section =“...
    编程 发布于2025-04-30

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3