React列表页如何保留加载更多的产品并返回原位置?
问题描述
我是React新手。我有一个产品列表,默认显示15个产品。点击“加载更多”按钮后,会再展示15个产品,总计30个。但当我点击通过“加载更多”加载出的产品进入详情页后,返回列表页时,已加载的产品消失,页面停在随机位置。如何保留点击按钮后加载的产品,且从详情页返回时能回到点击产品所在的位置?
[编辑]
以下是我认为需要修改的代码部分:
const [products, setProducts] = useState([]); const [loadingProducts, setLoadingProducts] = useState(true); const [loadingMore, setLoadingMore] = useState(false); const [currentPage, setCurrentPage] = useState(1); const handleLoadMore = (e) => { e.preventDefault(); setCurrentPage(previousCurrentPage => previousCurrentPage + 1); setLoadingMore(true); }; <LoadMore loadingMore={loadingMore} handleLoadMore={handleLoadMore} meta={meta} numberVisibleProducts={products.length} />
解决方案
一、保留已加载的产品数据
当前用useState存储的产品数据,会在组件卸载(跳转到详情页时)丢失。需要把已加载的产品和当前页码做持久化处理,这里推荐用sessionStorage结合useEffect同步状态:
修改状态初始化与同步逻辑
const [products, setProducts] = useState(() => { // 初始化时从sessionStorage读取保存的产品 const savedProducts = sessionStorage.getItem('savedProducts'); return savedProducts ? JSON.parse(savedProducts) : []; }); const [currentPage, setCurrentPage] = useState(() => { // 读取保存的页码 const savedPage = sessionStorage.getItem('currentPage'); return savedPage ? Number(savedPage) : 1; }); // 监听数据变化,自动同步到sessionStorage useEffect(() => { sessionStorage.setItem('savedProducts', JSON.stringify(products)); sessionStorage.setItem('currentPage', currentPage.toString()); }, [products, currentPage]);
确保数据是追加而非覆盖
请求新页产品时,要把新数据追加到现有数组里,不要直接替换:
// 假设你有根据页码获取产品的异步函数 useEffect(() => { const fetchProducts = async () => { currentPage === 1 ? setLoadingProducts(true) : setLoadingMore(true); try { const res = await api.getProducts(currentPage); // 追加新数据到现有列表 setProducts(prev => [...prev, ...res.data]); } catch (err) { console.error('加载产品失败', err); } finally { setLoadingProducts(false); setLoadingMore(false); } }; fetchProducts(); }, [currentPage]);
二、返回时恢复滚动位置
需要在点击产品跳转前记录当前滚动位置,返回列表页时读取并恢复:
1. 记录滚动位置
在产品项的点击事件中保存滚动位置:
const handleProductClick = (productId) => { // 保存当前滚动条的垂直位置 sessionStorage.setItem('scrollPosition', window.scrollY.toString()); // 跳转到详情页 navigate(`/product/${productId}`); };
2. 返回时恢复位置
在列表页组件挂载时,读取保存的位置并滚动:
useEffect(() => { const scrollPos = sessionStorage.getItem('scrollPosition'); if (scrollPos) { window.scrollTo(0, Number(scrollPos)); // 恢复后清除记录,避免下次进入列表页自动滚动 sessionStorage.removeItem('scrollPosition'); } }, []);
额外优化:区分“首次进入”和“从详情页返回”
如果用户从其他页面进入列表页,需要重置状态;只有从详情页返回时才保留数据。可以加个标记:
// 列表页挂载时判断 useEffect(() => { const isFromDetail = sessionStorage.getItem('isFromDetail'); if (!isFromDetail) { // 非详情页返回,重置数据 setProducts([]); setCurrentPage(1); sessionStorage.removeItem('savedProducts'); sessionStorage.removeItem('currentPage'); } sessionStorage.removeItem('isFromDetail'); }, []); // 详情页的返回按钮逻辑 const handleBack = () => { sessionStorage.setItem('isFromDetail', 'true'); navigate(-1); };
内容的提问来源于stack exchange,提问作者kayak
相关产品推荐
相关产品推荐

