如何在 React.js 中添加无限滚动

探索 React 中的无限滚动

您是否曾遇到过这样的网站或应用:当您向下滚动时,内容会不断加载并显示?这正是所谓的无限滚动,也称为“虚拟滚动”或“懒加载”。

无限滚动是一种流行的前端技术,它显著提升了浏览大量内容时的便利性。 它不仅优化了用户体验,尤其在移动设备上,还使得滚动更加流畅自然。

在 React 中实现无限滚动,有多种方法可选。 一种常见的方式是借助像 react-infinite-scroll-component 这样的第三方库。 此库的核心思想是,当用户滚动至页面底部时,它会触发特定的事件,从而提示我们加载更多内容。

当然,React 也提供内置的功能来帮助我们实现无限滚动。 例如,componentDidMount 生命周期方法,它会在组件首次挂载时被调用。 我们可以利用这个方法来加载初始数据。

后续数据的加载,可以结合使用 componentDidUpdate 方法,每当用户滚动到页面底部时,便触发数据加载操作。 此外,React Hooks 也提供了实现无限滚动功能的途径。

让我们深入了解如何使用 react-infinite-scroll-component 库。

安装 react-infinite-scroll-component

首先,您需要通过 npm 来安装这个库:

npm install react-infinite-scroll-component --save

在 React 中导入 react-infinite-scroll-component

安装完成后,将这个无限滚动库导入到您的 React 组件中:

import React from 'react'
import InfiniteScroll from 'react-infinite-scroll-component'
class App extends React.Component {
constructor() {
super()
this.state = {
items: [],
hasMore: true
}
}

componentDidMount() {
this.fetchData(1)
}
fetchData = (page) => {
const newItems = []
for (let i = 0; i < 100; i++) {
newItems.push(i )
}
if (page === 100) {
this.setState({ hasMore: false })
}
this.setState({ items: [...this.state.items, ...newItems] })
}
render() {
return (
<div>
<h2>无限滚动示例</h2>
<InfiniteScroll
dataLength={this.state.items.length}
next={this.fetchData}
hasMore={this.state.hasMore}
loader={<h4>加载中...</h4>}
endMessage={
<p style={{ textAlign: 'center' }}>
<b>恭喜,您已经看到了所有内容!</b>
</p>
}
>
{this.state.items.map((item, index) => (
<div key={index}>
{item}
</div>
))}
</InfiniteScroll>
</div>
)
}
}
export default App

这段代码首先从 react-infinite-scroll-component 库中导入了 ReactInfiniteScroll 组件。 然后,它创建了一个有状态的组件,并使用一个空的项目数组以及一个初始值为 truehasMore 标志来初始化组件的状态。

配置参数

componentDidMount 生命周期方法中,您需要调用 fetchData 方法,并传入 page 参数,将其设置为 1。 fetchData 方法负责从 API 获取数据。 在这个示例中,它生成了一些虚拟的数据,并创建了一个包含100个项目的数组。

page 参数达到 100 时,由于不再有更多数据,您可以将 hasMore 标志设置为 false。 这会阻止 InfiniteScroll 组件继续进行 API 调用。 最后,更新状态以反映新的数据。

render 方法使用 InfiniteScroll 组件,并传递一些属性。 dataLength 属性被设置为 items 数组的长度。 next 属性设置为 fetchData 方法。 hasMore 属性则直接绑定到 hasMore 标志。

loader 属性使组件渲染出一个加载指示器。 同样,当所有数据都加载完毕后,endMessage 属性会渲染出一条消息。

当然,您可以向 InfiniteScroll 组件传递更多的属性,但这些通常是最常用的属性。

使用 React 内置功能

React 本身提供了一些内置方法,可用于实现无限滚动。

第一种方法是 componentDidUpdate。 React 在组件更新后会调用这个方法。 您可以用它来检测用户是否已滚动到页面底部,如果是,则加载更多数据。

另一种方法是 scroll 事件,当用户滚动时,React 会触发此事件。 您可以使用它来追踪滚动的位置。 一旦用户滚动到页面底部,您便可以加载更多的数据。

以下是一个使用这些方法的 React 无限滚动示例:

import React, {useState, useEffect} from 'react'
function App() {
const [items, setItems] = useState([])
const [hasMore, setHasMore] = useState(true)
const [page, setPage] = useState(1)
useEffect(() => {
fetchData(page)
}, [page])
const fetchData = (page) => {
const newItems = []
for (let i = 0; i < 100; i++) {
newItems.push(i)
}
if (page === 100) {
setHasMore(false)
}
setItems([...items, ...newItems])
}
const onScroll = () => {
const scrollTop = document.documentElement.scrollTop
const scrollHeight = document.documentElement.scrollHeight
const clientHeight = document.documentElement.clientHeight
if (scrollTop + clientHeight >= scrollHeight) {
setPage(page + 1)
}
}
useEffect(() => {
window.addEventListener('scroll', onScroll)
return () => window.removeEventListener('scroll', onScroll)
}, [items])
return (
<div>
{items.map((item, index) => (
<div key={index}>
{item}
</div>
))}
</div>
)
}
export default App

这段代码使用了 useStateuseEffect Hooks 来管理状态和副作用。

useEffect Hook 中,它会使用当前的 page 值来调用 fetchData 方法。 fetchData 方法执行 API 调用来获取数据。 在此示例中,我们仅仅是生成了一些虚拟数据来演示技术。

for 循环使用 100 个整数来填充 newItems 数组。 如果 page 参数为 100,则将 hasMore 标志设置为 false。 这会阻止无限滚动组件继续调用 API。

最后,使用新数据来更新状态。

onScroll 方法会跟踪滚动的位置。 如果用户滚动到页面底部,就可以加载更多数据。

useEffect Hook 为 scroll 事件添加一个事件监听器。 当触发 scroll 事件时,它会调用 onScroll 方法。

在 React 中使用无限滚动既有优点也有缺点。 它能够改善用户界面,带来更流畅的体验,特别是在移动设备上。 然而,它也可能导致用户错过某些内容,因为他们可能无法向下滚动到足够远的位置看到所有信息。

在您的网站或应用中实施无限滚动技术前,务必权衡其利弊。

在 React.js 网站或应用程序中添加无限滚动,可以显著改善用户体验。 通过无限滚动,用户可以无需点击即可查看更多内容。 在 React.js 应用程序中使用无限滚动,还可以减少页面加载次数,进一步提升性能。

您还可以免费轻松地将 React 应用部署到 GitHub Pages。