【场景方案】还在用老套的方式实现下拉加载更多啊,最新react只需简单的代码即可实现

前言

下拉加载更多我想每个前端开发都遇到过,需要的时候就在网上搜,很有可能搜到的都是一些过去“老时代”的写法。前端发展的这么快,不抓紧跟上,你的代码编写只会越来越落伍。

本次文章就教你用react18+ahook+antd第三方库最简单的方式去实现一个下拉加载更多。


场景描述

数据结构:一般这种下拉加载的,数据都是以卡片式的样式呈现,数据结构一般为[{}, {}, ...]。然后下拉的新数据直接push到后面即可。

功能重点:这个功能的核心是怎么去监听到用户下拉到底了


响应式变量设计

响应式变量只需要这几个:

const [started, setStarted] = useState(false) // 是否已经开始加载(防抖,有延迟时间)
const [page, setPage] = useState(1) // 当前页码
const [list, setList] = useState([]) // 全部的列表数据,上划加载更多,累计
const [total, setTotal] = useState(0) // 后端返回的总数量
const haveMoreData = total > list.length // 是否还有数据可以加载

数据请求

咱们用到了ahooks里的useRequesthook:

const { run: load, loading } = useRequest(
  async () => {
    const data = await getQuestionListService({ // 请求数据的api
      page,
      pageSize: 10,
      keyword,
    })
    return data
  },
  {
    manual: true,
    onSuccess(result) {
      const { list: l = [], total = 0 } = result
      setList(list.concat(l)) // 累计推入
      setTotal(total)
      setPage(page + 1)
    },
  }
)

如果你要是不用ahooks就多声明一个loading响应式变量即可。


下拉加载更多(下拉区)的jsx

const LoadMoreContentElem = useMemo(() => {
  if (!started || loading) return <Spin />
  if (total === 0) return <Empty description="暂无数据" />
  if (!haveMoreData) return <span>没有更多了...</span>
  return <span>开始加载下一页...</span>
}, [started, loading, haveMoreData])

return (
  <>
    // ...
    <div className={styles.footer}>
      <div ref={containerRef}>{LoadMoreContentElem}</div>
    </div>
  </>

用getBoundingClientRect判断下拉区是否在屏幕显示器内

哎,这也不是什么新特性,好几年前就有了,可以用这个api去判断下拉区是否在屏幕显示器内,具体用法可以看https://blog.csdn.net/m0_52009348/article/details/119816872

不得不说随着es标准的发布,很多功能的实现已经被新的api替代了,只是我们不知道,都用着“土方法”去实现,引人深思啊

有了这个api我们就可以实时监听下拉区是否在屏幕显示器内,当然还要加个防抖机制:

const containerRef = useRef<HTMLDivElement>(null)
const { run: tryLoadMore } = useDebounceFn(
  () => {
    const elem = containerRef.current
    if (elem == null) return
    const domRect = elem.getBoundingClientRect()
    if (domRect == null) return
    const { bottom } = domRect
    // 出现在视图内
    if (bottom <= document.body.clientHeight) {
      load() // 真正加载数据
      setStarted(true)
    }
  },
  {
    wait: 1000,
  }
)

初始化且开启监听

万事俱备,只差触发

// 1. 当页面加载,或者搜索参数变化时,触发加载
useEffect(() => {
  tryLoadMore() // 加载第一页,初始化
}, [searchParams])

// 2. 当页面滚动时,触发加载
useEffect(() => {
  if (haveMoreData) {
    window.addEventListener('scroll', tryLoadMore) // 防抖
  }

  return () => {
    window.removeEventListener('scroll', tryLoadMore) // 解绑事件,重要!!!
  }
}, [searchParams, haveMoreData])

页面滚动的useEffect监听searchParams, haveMoreData设计的很有意思,当重新搜索数据时,后端返回新数据了,一切从头开始计算,如果haveMoreData为false,说明搜索出来的数据不用分页没有更多了,不需要开启监听了。


尾巴

下次遇到了一样的需求直接cv大法拿走用吧~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下拉刷新和上拉加载更多是移动开发中常用的交互方式,可以提高用户体验。在使用 React Native 进行开发时,可以使用第三方库 `react-native-refreshable-listview` 来实现这个功能。 下面是使用 `react-native-refreshable-listview` 实现下拉刷新和上拉加载更多代码示例: ```jsx import React, { useState, useEffect } from 'react'; import { RefreshableListView } from 'react-native-refreshable-listview'; import { View, Text } from 'react-native'; const App = () => { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(false); const fetchData = () => { setIsLoading(true); // 发起网络请求获取数据 // ... // 获取数据后新状态 setData([...data, ...newData]); setIsLoading(false); }; useEffect(() => { fetchData(); }, []); const renderRow = (rowData) => { return ( <View> <Text>{rowData}</Text> </View> ); }; return ( <RefreshableListView data={data} renderRow={renderRow} isRefreshing={isLoading} onRefresh={fetchData} onLoadMore={fetchData} paginationWaitingView={() => <Text>Loading...</Text>} /> ); }; export default App; ``` 在这个示例中,我们使用了 `useState` 和 `useEffect` 来管理组件状态和副作用。`fetchData` 函数用于发起网络请求获取数据,并新组件状态。`renderRow` 函数用于渲染数据。`RefreshableListView` 组件用于实现下拉刷新和上拉加载更多。其中,`isRefreshing` 和 `onRefresh` 属性用于控制下拉刷新,`onLoadMore` 属性用于控制上拉加载更多。`paginationWaitingView` 属性用于设置上拉加载更多时的等待状态。 这样,我们就完成了使用 `react-native-refreshable-listview` 实现下拉刷新和上拉加载更多的示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值