我們在應用程式和網頁中看到無限滾動,尤其是希望我們滾動的社交媒體。雖然無意識地滾動不好,但構建自己的無限滾動是很棒的。作為開發人員,我們應該嘗試重新創建我們在網上沖浪時看到的組件。它可以挑戰您在實現某些組件時了解更多資訊並跳出框框進行思考。
此外,如果您希望在應用程式中實現無限滾動,那麼您可以按照指南創建自己的滾動。您可以添加自己的程式碼來改善滾動的行為。
在本文中,我們將從頭開始建立一個無限滾動組件。它將涵蓋以下主題:
現在,讓我們開始吧。
我們將使用 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); } };
成功更改載入狀態後,我們可以實作 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。
在 React 中建立無限滾動元件可能是一次非常有益的體驗。它不僅可以增強您對滾動工作原理的理解,還可以教您有關狀態管理、事件偵聽器和去抖動等優化技術的知識。透過遵循本指南,您現在擁有了基本的無限滾動設置,您可以根據需要進行自訂和改進。
無論您是顯示電影資料、部落格文章或任何其他內容,此元件都是堅實的基礎。請記住,關鍵是透過仔細管理用戶滾動時獲取資料的時間和方式來確保流暢的用戶體驗。快樂編碼!
以上是在 React 中建立無限滾動元件的詳細內容。更多資訊請關注PHP中文網其他相關文章!