Reactreact-infinite-scroll-component 实现滚动加载

Posted 嘻嘻的妙妙屋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Reactreact-infinite-scroll-component 实现滚动加载相关的知识,希望对你有一定的参考价值。

react-infinite-scroll-component 实现滚动加载

效果

index.tsx

import useState, useEffect from 'react'
import observer from 'mobx-react-lite'
import styles from './index.module.scss'
import recordStore, IData from 'src/store/recordStore'
import formatTimestamp from 'src/utils'
import InfiniteScroll from 'react-infinite-scroll-component'

const TableContent: React.FC = props => 
  // 查询月份下拉框
  const [dropDown, setDropDown] = useState(false)
  const handleOpen = (e: any) => 
    e.stopPropagation()
    e.nativeEvent.stopImmediatePropagation()
    setDropDown(!dropDown)
  
  useEffect(() => 
    document.body.addEventListener('click', () => 
      setDropDown(false)
    )
    return () => 
      document.body.removeEventListener('click', () => 
        setDropDown(false)
      )
    
  , [])
  const selectMonth = (e: any) => 
    // console.log(e.currentTarget.getAttribute('data-name'))
    setDropDown(!dropDown)
    const month = e.currentTarget.getAttribute('data-name')
    recordStore.setSelectedMonth(month)
  
  // 获取最近月份记录
  useEffect(() => 
    if (recordStore.selectedMonth) 
      recordStore.fetchMonthlyData()
    
  , [recordStore.selectedMonth])
  return (
    <div className=styles.container>
      <div className=styles.title>
        <div className=styles.sum>合计:recordStore.totalAmount</div>
        <div className=styles.search>
          查询
          <div className=styles.select>
            <ul>
              <li>
                <div className=styles.head onClick=handleOpen>
                  <span>recordStore.selectedMonth</span>
                  <span className=styles.icon_down></span>
                </div>
                <ul className=dropDown ? styles.option : styles.hide>
                  recordStore.monthList &&
                    recordStore.monthList.map((item: string, index: number) => (
                      <li key=`month_$index` data-name=item className=styles.item onClick=selectMonth>
                        item
                      </li>
                    ))
                </ul>
              </li>
            </ul>
          </div>
        </div>
      </div>
      <div className=styles.table>
        <div className=styles.thead>
          <p>时间</p>
          <p>昵称</p>
          <p>项目</p>
          <p>数量</p>
          <p>花费</p>
        </div>
        <InfiniteScroll
          className=styles.scroll
          dataLength=recordStore.dataList.length
          next=() => 
            recordStore.fetchDataList()
          
          hasMore=recordStore.hasMore
          height=320
          key=recordStore.scrollKey
        >
	        <div className=styles.tbody>
	          recordStore.dataList &&
	            recordStore.dataList.map((item: IData, index: number) => (
	              <div key=`data_tab1_$index` className=styles.row>
	                <p>formatTimestamp(item.createTime)</p>
	                <p className=styles.nickname>item.nickname</p>
	                <p>item.itemName</p>
	                <p>item.amount</p>
	                <p>item.citrineAmount</p>
	              </div>
	            ))
	          !recordStore.dataList && (
	            <div style=textAlign: 'center', lineHeight: '200px', color: 'rgba(0,0,0,0.3)'>暂无数据</div>
	          )
	        </div>
        </InfiniteScroll>
      </div>
    </div>
  )


export default observer(TableContent)

recordStore.ts

import makeAutoObservable, runInAction from 'mobx'
import formatMonth from 'src/utils'
import getDataList, listMonth from 'src/services/api'

export interface IData 
  nickname: string // 昵称
  createTime: number // 时间
  itemName: string // 项目名称
  itemId: number // 项目id
  amount: number // 数量
  citrineAmount: number // 花费


class RecordStore 
  scrollKey = 'init1' // InfiniteScroll key1
  scrollKey2 = 'init2'	// InfiniteScroll key2
  selectedMonth = '' // 选中月份
  monthList: Array<string> = [] // 月份列表
  totalAmount: number // 总额度1
  totalAmount2: number // 总额度2
  dataList: Array<IData> = [] // 数据列表1
  page = 0 // 当前页码1
  hasMore = true // 有无下一页信息1
  dataList2: Array<IData> = [] // 数据列表2
  page2 = 0 // 当前页码2
  hasMore2 = true // 有无下一页信息2
  constructor() 
    makeAutoObservable(this)
  
  // 更改选中月份
  async setSelectedMonth(month = '') 
    runInAction(() => 
      this.selectedMonth = month
    )
  
  // 获取月份列表
  async getMonthList() 
    const res = await listMonth()
    if (res.status === 0) 
      runInAction(() => 
        this.monthList = res.data
        this.selectedMonth = res.data.length > 0 && res.data[0]
      )
    
  
  // 获取月份记录
  async fetchMonthlyData(tab = 1, size = 11) 
    if (tab === 1) 
      runInAction(() => 
        this.scrollKey = Math.random().toString(36).substr(2)
        this.page = 1
        this.hasMore = true
      )
     else 
      runInAction(() => 
        this.scrollKey2 = Math.random().toString(36).substr(2)
        this.page2 = 1
        this.hasMore = true
      )
    
    // ↓↓↓↓↓↓↓↓↓↓-测试数据-↓↓↓↓↓↓↓↓↓↓
    const item = 
      yyno: 1,
      nickname: '昵称昵称',
      createTime: 1655275863,
      itemName: '金拱门',
      itemId: 1,
      amount: 100,
      citrineAmount: 1000,
    
    const d: any = []
    for (let i = 0; i < 11; i++) 
      d.push(item)
    
    // ↑↑↑↑↑↑↑↑↑↑-测试数据-↑↑↑↑↑↑↑↑↑↑
    const res = await getDataList(
      tab: tab,
      month: formatMonth(this.selectedMonth),
      size: size,
      page: tab === 1 ? this.page : this.page2,
    )
    if (res.status === 0) 
      if (tab === 1) 
        runInAction(() => 
          // ↓↓↓↓↓↓↓↓↓↓-测试数据-↓↓↓↓↓↓↓↓↓↓
          res.data.datas = d
          // ↑↑↑↑↑↑↑↑↑↑-测试数据-↑↑↑↑↑↑↑↑↑↑
          this.totalAmount = res.data.totalAmount
          this.dataList = res.data.datas
          if ((this.dataList && this.dataList.length < size) || !this.dataList) 
            this.hasMore = false
          

          // ↓↓↓↓↓↓↓↓↓↓-测试数据加载完毕-↓↓↓↓↓↓↓↓↓↓
          if (!this.dataList || (this.dataList && this.dataList.length > 100)) 
            this.hasMore = false
          
          // ↑↑↑↑↑↑↑↑↑↑-测试数据加载完毕-↑↑↑↑↑↑↑↑↑↑
        )
       else 
        runInAction(() => 
          this.totalAmount2 = res.data.totalAmount
          this.dataList2 = res.data.datas && this.dataList2.concat(...res.data.datas)
          if ((this.dataList2&& this.dataList2.length < size) || !this.dataList2) 
            this.hasMore2 = false
          
        )
      
    
  
  // 分页获取帮扶/被帮扶记录
  async fetchDataList(tab = 1, size = 11) 
    if (tab === 1) 
      runInAction(() => 
        this.page++
      )
     else 
      runInAction(() => 
        this.page2++
      )
    
    // ↓↓↓↓↓↓↓↓↓↓-测试数据-↓↓↓↓↓↓↓↓↓↓
    const item = 
      nickname: '我的昵称',
      createTime: 1655275863,
      itemName: '麦当当',
      itemId: 1,
      amount: 100,
      citrineAmount: 1000,
    
    const d: any = []
    for (let i = 0; i < 11; i++) 
      d.push(item)
    
    // ↑↑↑↑↑↑↑↑↑↑-测试数据-↑↑↑↑↑↑↑↑↑↑
    const res = await getDataList(
      tab: tab,
      month: formatMonth(this.selectedMonth),
      size: size,
      page: tab === 1 ? this.page : this.page2,
    )
    if (res.status === 0) 
      if (tab === 1) 
        runInAction(() => 
          // ↓↓↓↓↓↓↓↓↓↓-测试数据-↓↓↓↓↓↓↓↓↓↓
          res.data.datas = d
          // ↑↑↑↑↑↑↑↑↑↑-测试数据-↑↑↑↑↑↑↑↑↑↑

          this.totalAmount = res.data.totalAmount
          this.dataList = res.data.datas && this.dataList.concat(...res.data.datas)
          if ((this.dataList && this.dataList.length < size) || !this.dataList) 
            this.hasMore = false
          

          // ↓↓↓↓↓↓↓↓↓↓-测试数据加载完毕-↓↓↓↓↓↓↓↓↓↓
          if (!this.dataList || (this.dataList && this.dataList.length > 100)) 
            this.hasMore = false
          
          // ↑↑↑↑↑↑↑↑↑↑-测试数据加载完毕-↑↑↑↑↑↑↑↑↑↑
        )
       else 
        runInAction(() => 
          this.totalAmount2 = res.data.totalAmount
          this.dataList2 = res.data.datas && this.dataList2.concat(...res.data.datas)
          if ((this.dataList2 && this.dataList2.length < size) || !this.dataList2) 
            this.hasMore2 = false
          
        )
      
    
  


export default new RecordStore()

index.module.scss

li 
  list-style: none;

.title 
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 416px;
  margin: 18px 12px 0;
  padding: 0 18px 0 22px;
  font-size: 12px;
  .sum 
    color: #ff6600;
  
  .search 
    display: flex;
    line-height: 24px;
    ul 
      margin-left: 8px;
      width: 96px;
      height: 24px;
      border: 1px solid #dcdcdc;
      border-radius: 5px;
      background: #eeeeee;
      font-size: 12px;
      cursor: pointer;
      li 
        position: relative;
        .head 
          overflow: hidden;
          width: 100%;
          height: 24px;
          box-sizing: border-box;
          line-height: 20px;
          padding-left: 15px;
          .icon_down 
            position: absolute;
            top: 8px;
            right: 16px;
            width: 11px;
            height: 7px;
            background-image: url(../imgs/icon_down.png);
            background-size: 100%;
          
        
        .option 
          width: 96px;
          position: absolute;
          top: 23px;
          left: -9px;
          border以上是关于Reactreact-infinite-scroll-component 实现滚动加载的主要内容,如果未能解决你的问题,请参考以下文章