问题点
- 如果一次加载 10 条数据,但是页面高度很高,不会显示滚动条,比如再大屏幕显示,会导致 hasMore=true
- loader 内容会一直显示,但是不加载数据,给人卡顿的体验。
解决
- 只要有滚动条,load 就显示正常
- 初始化多加载些数据,比如 100 条,然后每次滚动触发 next 再次加载
无限滚动方案二
Intersection Observer API
案例参考
https://dev.to/vishnusatheesh/exploring-infinite-scroll-techniques-in-react-1bn0
react-infinite-scroll-component
https://github.com/ankeetmaini/react-infinite-scroll-component
https://www.npmjs.com/package/react-infinite-scroll-component
https://www.jianshu.com/p/4bb28664ad74
// yarn add react-infinite-scroll-componentimport React, { useRef } from 'react'import { Skeleton, Divider } from 'antd'import InfiniteScroll from 'react-infinite-scroll-component'import clsx from 'clsx'type IProps = {children: React.ReactNode,fetchMore: () => void;dataLength: number;hasMore: boolean;loading: boolean;};function ScrollList(props: IProps){const {children,fetchMore,dataLength,hasMore = false,loading = false,className} = props;const domRef = useRef<HTMLDivElement>(null);return (<sectionref={domRef}className={clsx('overflow-x-hidden overflow-y-auto ',className)}><InfiniteScrolldataLength={dataLength}next={fetchMore}hasMore={hasMore}scrollableTarget={domRef.current}// 小于20条数据全部展示endMessage={dataLength > 20? <Divider plain>已全部加载</Divider>: false}loader={(<Skeletonavatar={{ shape: 'square' }}paragraph={{ rows: 3 }}activeclassName="mt16"/>)}>{children}</InfiniteScroll></section>);}export default ScrollList;
InfiniteScroll
import React, { useEffect, useMemo, useState } from 'react';import { useRequest } from 'ahooks';import { ScrollList, InputSearch, isSuccess, requestOptions } from '@/components';const initPage = { page: 1, limit: 10 }function App() {const [dataSource, setDataSource] = useState([]);const [page, setPage] = useState(initPage);// 初始化数据标识const [initFlag, setInitFlag] = useState(true);// 获取列表const { data = { total: 0 }, runAsync, loading } = useRequest(getUsers, requestOptions);const hasMore = useMemo(() => dataSource.length < data.total, [dataSource, data.total]);useEffect(() => {init();}, [page, initFlag]);async function init() {const res = await runAsync(page);if (!isSuccess(res)) return;// 初始化数据if (flag) {return setSource(res.data);}// 加载更多合并数据setDataSource(prevState => prevState.concat(res.data));}// 向下滚动触发的事件,用于更新 page++async function fetchMore() {// 合并数据,不要初始化setInitFlag(false);setPage(prevState => {return { ...prevState, page: prevState.page + 1 }});}async function onSearch(name) {const payload = name ? { ...initPage, name } : initPage;// 搜索初始化数据setInitFlag(true);setPage(payload);}function renderItem(item) {return (<Col span={8} key={item.id}><Card>{item.name}</Card></Col>)}return (<PageContainer><InputSearch onSearch={onSearch} /><Spin spinning={page.page === 1 ? loading : false}><ScrollListfetchMore={fetchMore}hasMore={hasMore}dataLength={dataSource.length}><Row gutter={[24, 24]} className="w-full">{dataSource.map(renderItem)}</Row></ScrollList></Spin></PageContainer>)}export default App
推送列表滚动
https://www.jq22.com/yanshi22468
https://www.jq22.com/demo/jquerylistScroll201911081901/
