在react中实现无限滚动时,如何从数组的开头删除多余的元素?

How to remove redundant elements from the beginning of an array when implementing infinite scroll in react?

提问人:Денис Ястребов 提问时间:11/14/2023 更新时间:11/14/2023 访问量:21

问:

有一个页面接收 YouTube 视频的数据流。我将这些数据输出到页面,并使用观察器实现无限滚动。 可视化:在此处输入图像描述

问题。当数组中有超过 200-300 个包含数据的项目时,性能问题就开始了。如果你从数组的开头开始删除元素,那么自然而然地整个元素列表就会向上移动,这在功能上是不方便的。

// types
import {VideoAtFlow} from '../../../../types';
// react- redux
import {useCallback, useEffect, useRef, useState } from 'react';
import {useGetFeedMutation} from '../../../../app/services/queries/videoflow';
import {selectVideoflow} from '../../../../features/video-flow/videoflowSlice';
import {useAppSelector} from '../../../../hooks/hooks';
// components
import {DisplayContent} from './display-content/DisplayContent';
import {IfSpin} from '../../../../widgets';
// scss
import mod from './style.module.scss';

export const VideoFlowContentComponents = () => {
    const [video, setVideo] = useState<VideoAtFlow[]>([]);
    const [fetching, setFetching] = useState(false);
    const [count, setCount] = useState(0);
    const loaderRef = useRef(null);

    const [getVideo] = useGetFeedMutation()

    const param = {
        from: count,
        date_published_at: "now-1w",
        sort: "views_per_hour",
        category: "any",
        country: "RU",
        min_iq_score: 0,
        max_iq_score: 100,
        content_type: "any"
    }

    const fetchData = useCallback(async () => {
        if (fetching) return;
        requestData()
    }, [count, fetching]);
    
    useEffect(() => {
        const observer = new IntersectionObserver((entries) => {
          const target = entries[0];
          if (target.isIntersecting) {
            fetchData();
            setCount(count + 20)
          }
        });
    
        if (loaderRef.current) {
          observer.observe(loaderRef.current);
        }
    
        return () => {
          if (loaderRef.current) {
            observer.unobserve(loaderRef.current);
          }
        };
    }, [fetchData]);

    const requestData = async () => {
        setFetching(true);
        const response = await getVideo(param);
        const data = 'data' in response ? response.data : [];
        setVideo((newArray: any) => {
            let array = [...(newArray || []), data]
            let combinedArray = [].concat(...array)
            return combinedArray
        });
        setFetching(false);
    }

    const {flowOrPlaylists} = useAppSelector(selectVideoflow);
    const data = flowOrPlaylists ? [] : video 
    
    return (
        <div className={mod.wrapper}>
            <DisplayContent
                data={data}
            />
            <div
                className={mod.triggerbox}
                ref={loaderRef}>{fetching && <IfSpin height='10%'/>}
            </div>
        </div>
    );
};

我们需要以某种方式优化这样一个过程,即当包含数据的数组超过 100 个元素时,每个新查询都会从数组的开头删除 20 个元素。在这种情况下,浏览器中带有元素的“磁贴”不应以任何方式更改、跳转、移动等。

javascript reactjs 无限滚动 观察者模式

评论

0赞 Egge 11/14/2023
在性能方面,您是否遵循了所有推荐的做法?你的组件是纯粹的、记忆的、有稳定的密钥吗?

答: 暂无答案