Как поддерживать большое динамическое состояние React, определяющее дочерние элементы?

У меня есть компонент React с сокетом, который получает информацию, обновляющую его состояние. В конечном итоге состояние представляет собой около 10000 объектов JSON, каждый из которых представляет pointPrimitive для рендеринга в приложении цезия/резиума. Редактирование этого списка несколько раз в секунду обходится дорого, и даже оценка необходимости повторного рендеринга запомненных дочерних элементов обходится дорого в таком масштабе. Что я могу сделать, чтобы этот компонент работал с разумной скоростью или реорганизовал его?

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

import { io } from "socket.io-client";
import PointCollection from '../TrackPoints/PointCollection';

import { getServerURL } from '../../lib/getServerURL';

const enoughPoints = 1;
const delayMSec = 1000 * .5;
const expireSec = 45; //This should depend on the class of item. Maybe anomalous things should last longer
const serverURL = getServerURL();


const PointManager = (props: {modes: any, onClick: Function, viewRef}) => {
    
    const [pointsDict,   setPointsDict] = useState({});
    const mode = props.modes.ADSB;
    
    //TODO: figure out whether to use a list of JSONs or a proper list of components
    //There may be performance consequences to either. For now, this is cleaner to code
    const addPoint = (JSONEntry) => {
        const k = JSONEntry.react_key;
        const oldJSON = pointsDict[k] === undefined ? [] : pointsDict[k];
        
        let newJSON = JSONEntry;
        if (oldJSON.length > 0) {
            newJSON.isAnomalous = oldJSON[oldJSON.length-1].isAnomalous;

        } else {
            newJSON.isAnomalous = false;
        }

        setPointsDict((pointsDict) => {
            const copyFoo = { ...pointsDict};
            if(copyFoo[k] === undefined) {
                copyFoo[k] = [newJSON];
                return copyFoo;
            }
            copyFoo[k].push(newJSON);
            globalThis.SCJJ = copyFoo;
            return copyFoo;
        });
    };



    const staleOutPoints = (expireSec: number) => {
        setPointsDict((pointsDict) => {
            const keys = Object.keys(pointsDict);
            const t = Date.now()/1000;
            let newPoints = {};
            keys.map((trackID) => {
                const pts = pointsDict[trackID];
                let ptsFilter = pts.filter((pt,idx) => t - pt.TIMESTAMP < expireSec);

                newPoints[trackID] = ptsFilter;
            });
            return newPoints;
        });
    };

    //Control point time-out
    useEffect(() => {
        const interval = setInterval(() => staleOutPoints(expireSec), delayMSec);
        return () => clearInterval(interval);
    }, []);
    
    //points socket
    useEffect(() => {
        const format = (mode == "live" ? "LIVE" : "DEMO");
        console.log("Setting up stream with format " + format);
        
        const socketIOSocket = io(serverURL,{});


    async function fetchStream() {
        socketIOSocket.on('connect', function() {
            console.log('connected to points server!')
            socketIOSocket.emit('please_send_JSON', {
                "format_requested": format,
        })
    });
        
        socketIOSocket.on('JSON_entry', function(msg) {
            addPoint(msg);
        });

    }

    fetchStream();

    return () => {
        console.log("cleanup called");
        socketIOSocket.disconnect();
    };
    }, [mode]);


    return(
        <>
            {/* These are all rendering with every new point. Maybe there's a way to prevent this*/} 
            <PointCollection points={pointsDict}></PointCollection>
        </>
    )
};


export default PointManager;

Я многое сделал, чтобы уменьшить время рендеринга дочерних элементов и обеспечить минимальный повторный рендеринг родительского компонента. Я пробовал сгладить. Я пробовал изменить типы данных на immutable.js, но это был не идеальный вариант использования.

0 ответов

Другие вопросы по тегам