react列表滚动加载下一页

837 阅读1分钟

一、效果

动图.gif

二、ul li结构实现

可以使用原生事件,也可以使用插件(react-infinite-scroll-component),本来想着把卡片模式和表格模式都用ul li实现,将ul li的样式写成和表格一样就行了,所以使用插件做了

  1. 下载插件 npm i react-infinite-scroll-component
  2. 引入 import InfiniteScroll from 'react-infinite-scroll-component'
  3. 使用时需要在外层包一层div,并且设置id
        <div className={styles.addressList} id="addressList">
          <InfiniteScroll
            dataLength={dataSource.length}
            next={handleNext}
            hasMore={dataSource.length < total}
            loader={<Skeleton avatar paragraph={{ rows: 1 }} active />}
            // endMessage={<Divider plain>已加载完毕 🤐</Divider>}
            scrollableTarget="addressList"
          >
            <ul className={styles.first}>
              {dataSource.map(item => (
                <li key={item.userOrgId}>
                  ...一些DOM
                </li>
              ))}
            </ul>
          </InfiniteScroll>
        </div>

滚动事件回调:

  const handleNext = async () => {
    if (loading) return
    setLoading(true)
    const { code, data } = await listApi(params)
    if (code === 200) {
      const { rows, total } = data
      setTotal(total)
      setDataSource(params.pageNum === 1 ? rows : [...dataSource, ...rows])
      setLoading(false)
      params.pageNum++
    } else {
      setLoading(false)
    }
  }

三、ant-table结构实现

为什么要使用table结构?

因为ul li滚动时,th也跟着一起滚动,而table可以做到固定住表头。使用表格就得要自己写滚动事件,感觉table可以替代ul li的写法

  1. table外层包一层div,定义滚动事件
        <div className={styles.addressList} onScrollCapture={onScrollHandle}>
          <Table
            ref={tableRef}
            columns={columns}
            dataSource={dataSource}
            pagination={false}
            scroll={{ y: `calc(100% - 49px)` }} // 父级的高度要设置为100%,这句代码才有效
            rowKey="userOrgId"
          />
        </div>
  1. 滚动事件回调(注意只能是向下滚动时才能触发)
  let initTop = 0
  const onScrollHandle = () => {
    const tableBody = tableRef.current.querySelector('.ant-table-body')
    const { clientHeight, scrollHeight, scrollTop } = tableBody
    const scroll = scrollTop - initTop
    initTop = scrollTop
    const direction = scroll <= 0 ? 'up' : 'down'
    const distance = scrollHeight - (scrollTop + clientHeight) // 滚动条距离底部的距离
    if (distance < 20 && direction === 'down') {
      if (total > dataSource.length) handleNext()
    }
  }