You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:22:56