react ts 移动端页面分页,触底加载下一页
index.tsx
import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch, useLocation } from "dva";
import styles from './index.less';const List = () => {const location = useLocation();const searchParams = new URLSearchParams(location.search);const dispatch = useDispatch();const [loading, setLoading] = useState(false); const [finished, setFinished] = useState(false); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(10); const [data, setData] = useState([]); const [screenHeight, setScreenHeight] = useState(window.innerHeight); useEffect(() => {const handleResize = () => {setScreenHeight(window.innerHeight);};window.addEventListener("resize", handleResize);return () => window.removeEventListener("resize", handleResize);}, []);const getList = async (page) => {if (loading || finished) return;setLoading(true);try {dispatch({type: "",payload: {url:`你的接口`,type: "POST",body: {page: page,rows: pageSize},header: { "你的请求头参数" },},callback: res => {if (res.result === "1" && res.rows.length > 0) {setData((prevData) => [...prevData, ...res.rows]); if (res.rows.length < pageSize) {setFinished(true); }} else {setFinished(true); }},});} catch (error) {console.error("数据加载失败:", error);} finally {setLoading(false);}};useEffect(() => {getList(1);}, []);useEffect(() => {const container = document.querySelector(`.${styles.cardListContainer}`);if (!container) return;const handleScroll = () => {const { scrollTop, clientHeight, scrollHeight } = container;if (scrollTop + clientHeight >= scrollHeight - 10 && !loading && !finished) {setPage((prevPage) => prevPage + 1); }};container.addEventListener("scroll", handleScroll);return () => container.removeEventListener("scroll", handleScroll);}, [page, loading, finished]);useEffect(() => {if (page > 1) {getList(page); }}, [page]);return (<divclassName={styles.cardListContainer}style={{ height: screenHeight, overflowY: "auto" }} >{}{data.map((item) => (<div key={item.id} className={styles.card}><div className={styles.cardContent}><div><span className={styles.phone}>{item.phone}</span></div><div><span className={styles.remark}> {item.remark || "无备注"}</span></div></div></div>))}{}{loading && <div className={styles.loading}>加载中...</div>}{}{finished && <div className={styles.finished}>已显示全部数据</div>}</div>);
};export default List;
index.less
.cardListContainer {width: 100%;margin: 0 auto;padding: 0.2rem;overflow-y: auto;background: #FFF;padding-top: 0.85rem;
}
.cardListContainer::-webkit-scrollbar {display: none;
}
.card {width: 100%;padding: 0.2rem;margin-bottom: 0.12rem;display: flex;flex-direction: column;border-radius: 0.06rem;background: rgba(0, 0, 0, 0.03);
}.cardContent {display: flex;justify-content: space-between;align-items: center;div {display: inline-grid;}.phone {color: #101010;font-size: 0.15rem;font-style: normal;font-weight: 300;line-height: 0.24rem;}.remark {color: rgba(29, 29, 30, 0.70);font-size: 0.12rem;font-style: normal;font-weight: 300;line-height: 0.18rem;}
}
.loading {text-align: center;font-size: 0.12rem;color: rgba(29, 29, 30, 0.20);padding: 0.1rem;
}
.finished {text-align: center;font-size: 0.12rem;color: rgba(29, 29, 30, 0.20);padding: 0.1rem;
}