首頁  >  文章  >  web前端  >  在 React 中建立無限滾動元件

在 React 中建立無限滾動元件

WBOY
WBOY原創
2024-08-26 21:45:021101瀏覽

介紹

我們在應用程式和網頁中看到無限滾動,尤其是希望我們滾動的社交媒體。雖然無意識地滾動不好,但構建自己的無限滾動是很棒的。作為開發人員,我們應該嘗試重新創建我們在網上沖浪時看到的組件。它可以挑戰您在實現某些組件時了解更多資訊並跳出框框進行思考。

此外,如果您希望在應用程式中實現無限滾動,那麼您可以按照指南創建自己的滾動。您可以添加自己的程式碼來改善滾動的行為。

在本文中,我們將從頭開始建立一個無限滾動組件。它將涵蓋以下主題:

  • 環境設定
  • 建構組件
  • 加 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 (
        <div className="App">
          <header className="App-header">
            Popular movies according to Tmdb
            <div className="movieCardContainer">
              {data.length > 1 &&
                data.map((item) => {
                  return (
                    <MovieCard
                      key={item.id}
                      title={item.original_title}
                      description={item.overview}
                      rating={item.vote_average}
                      imageURL={item.poster_path}
                    />
                  );
                })}
              {loading && <h1>Loading....</h1>}
            </div>
          </header>
        </div>
      );
    }

    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 (
        <div className="movieCard">
          <img src={imagePath} height={400} />
          <div className="movieInfo">
            <h3>{title}</h3>
            <p>{description}</p>
            <p>{rating.toFixed(1)}⭐</p>
          </div>
        </div>
      );
    };

這是應用程式的 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 < window.scrollY + window.innerHeight) {
        setLoading(true);
      }
    };
  • scrollHeight :此屬性傳回內容的總高度,包括螢幕上看不見的部分。因此,它將是總的可滾動區域。
  • scrollY:傳回文件從頂部垂直捲動的像素數的屬性。所以這將是已滾動的區域。
  • innerHeight:傳回瀏覽器Windows內容區域高度的屬性。它將是滾動條的寬度。它被添加到scrollY,以便當我們到達內容時而不是當我們傳遞內容時發生獲取。 ## useEffect

成功更改載入狀態後,我們可以實作 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 <
          window.scrollY + window.innerHeight
        ) {
          setLoading(true);
        }
      };

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

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

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

      return (
        <div className="App">
          <header className="App-header">
            Popular movies according to Tmdb
            <div className="movieCardContainer">
              {data.length > 1 &&
                data.map((item) => {
                  return (
                    <MovieCard
                      key={item.id}
                      title={item.original_title}
                      description={item.overview}
                      rating={item.vote_average}
                      imageURL={item.poster_path}
                    />
                  );
                })}
              {loading && <h1>Loading....</h1>}
            </div>
          </header>
        </div>
      );
    }

    export default App;

這是演示應用程式工作原理的 GIF。

Building an Infinite Scroll Component in React

結論

在 React 中建立無限滾動元件可能是一次非常有益的體驗。它不僅可以增強您對滾動工作原理的理解,還可以教您有關狀態管理、事件偵聽器和去抖動等優化技術的知識。透過遵循本指南,您現在擁有了基本的無限滾動設置,您可以根據需要進行自訂和改進。

無論您是顯示電影資料、部落格文章或任何其他內容,此元件都是堅實的基礎。請記住,關鍵是透過仔細管理用戶滾動時獲取資料的時間和方式來確保流暢的用戶體驗。快樂編碼!

以上是在 React 中建立無限滾動元件的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn