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

React JS中滚动加载列表如何置顶localStorage存储的选中项?

解决滚动分段渲染列表中选中项置顶的问题

问题核心

你当前的分段渲染逻辑是先从大数组中截取前itemsToShow条,再处理置顶,这会导致不在初始截取范围内的选中项无法被置顶显示。而之前的updateLargeArray函数直接修改了整个大数组,会把未被截取的非选中项也过滤掉,反而破坏了分段渲染的逻辑。

解决方案:先处理置顶,再分段截取

调整逻辑顺序:先把所有选中项提取出来,再从剩余非选中项中补足需要显示的数量,确保选中项优先被渲染。

1. 优化置顶逻辑函数

替换原有的updateLargeArray,实现“优先显示选中项,再补充非选中项”的逻辑:

export const getTopPrioritizedList = (largeArray, globalItems, showCount) => {
  // 无选中项时直接返回分段数据
  if (!globalItems || globalItems.length === 0) {
    return largeArray.slice(0, showCount);
  }

  const globalItemIds = new Set(globalItems.map(item => item.ID));
  // 过滤出大数组中存在的有效选中项(避免localStorage存无效数据)
  const validSelectedItems = globalItems.filter(item => 
    largeArray.some(largeItem => largeItem.ID === item.ID)
  );
  // 分离非选中项
  const nonSelectedItems = largeArray.filter(item => !globalItemIds.has(item.ID));

  // 计算需要从非选中项中补充的数量:如果选中项数量超过showCount,就显示全部选中项
  const needNonSelected = Math.max(showCount - validSelectedItems.length, 0);
  // 合并结果:选中项在前,非选中项在后补足数量
  return [...validSelectedItems, ...nonSelectedItems.slice(0, needNonSelected)];
};

2. 修改自定义Hook的逻辑

更新useOptimizeListRenderPerformance,将置顶逻辑放在分段截取之前,并添加globalItems作为参数:

import React, { useState, useEffect } from "react";

const useOptimizeListRenderPerformance = (
  largeListArray,
  additionalFn,
  FnParams,
  ApplyFilter,
  globalItems // 新增选中项参数
) => {
  const [itemsToShow, setItemsToShow] = useState(5);
  const [list, setList] = useState([]);
  const [startY, setStartY] = useState(0);
  const [activated, setActivated] = useState(false);
  const [firstCall, setFirstCall] = useState(true);

  const handleScroll = (e) => {
    if (e.deltaY > 0) {
      setItemsToShow((prev) => prev + 5); // 匹配描述的"每次多显示5条",原逻辑是+1可自行改回
    } else {
      setItemsToShow((prev) => (prev > 5 ? prev - 5 : prev));
    }
  };

  const handleTouchStart = (e) => {
    setStartY(e.touches[0].clientY);
  };

  const handleTouchMove = (e) => {
    const currentY = e.touches[0].clientY;
    if (currentY > startY) {
      setItemsToShow((prev) => prev + 5);
    } else {
      setItemsToShow((prev) => (prev > 5 ? prev - 5 : prev));
    }
  };

  useEffect(() => {
    if (largeListArray) {
      let updatedList;
      // 优先处理选中项置顶
      updatedList = getTopPrioritizedList(largeListArray, globalItems, itemsToShow);
      
      // 执行原有的附加函数逻辑
      if (additionalFn) {
        updatedList = additionalFn(updatedList, ...FnParams);
      }
      
      // 应用过滤逻辑(如果有)
      setList(ApplyFilter ? ApplyFilter(updatedList, FnParams) : updatedList);
    }
  }, [largeListArray, itemsToShow, FnParams, ApplyFilter, globalItems]); // 加入globalItems依赖

  useEffect(() => {
    setActivated(true);
    setFirstCall(false);
  }, []);

  return {
    list,
    handleTouchMove,
    handleScroll,
    handleTouchStart,
    activated,
    firstCall,
  };
};

export default useOptimizeListRenderPerformance;

3. 使用Hook时传入选中项

在组件中调用Hook时,从localStorage取出选中项并传入:

const savedSelectedItems = JSON.parse(localStorage.getItem('selectedItems')) || [];
const { list, handleScroll, ...rest } = useOptimizeListRenderPerformance(
  shoppingItems,
  yourAdditionalFn,
  yourFnParams,
  yourApplyFilter,
  savedSelectedItems
);

关键说明

  • 修正了Hook中滚动时的步长为+5/-5,匹配你描述的“每次多显示5条”,若原逻辑就是+1可自行改回
  • 确保选中项无论是否在初始大数组的前N条,都会被优先显示
  • 过滤了localStorage中可能存在的无效选中项(ID不在大数组中的项)
  • 保持了分段渲染的性能优势,只渲染需要显示的条目

内容的提问来源于stack exchange,提问作者Haytham Kenway

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 15:42:02