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

React中大数据集变量赋值避免重置的最优方案咨询

最优赋值方案

针对大型数据集的场景,推荐以下几种方案,既避免useState带来的不必要重渲染,又解决普通变量随组件重渲染被重置的问题:

1. 使用useRef存储大型数据

useRef的.current属性不会随组件重渲染被重置,适合存储不需要触发全局UI更新的大型数据集(Recharts图表会自动监听传入的data变化,只要数据更新后组件能获取到最新值即可)。

修改你的代码示例:

export default function Page(){
    // ... 保留原有状态定义
    const pieChartDataRef = React.useRef<any[]>([]);
    const barChartDataRef = React.useRef<any[]>([]);
    const treeMapDataRef = React.useRef<any[]>([]);

    useEffect(() => {
        switch (selectedOrganisation) {
            case ALUAN_COCONUTS:
                // 对应企业的数据处理逻辑
                break;
            case BLANEY_FARM:
                // 对应企业的数据处理逻辑
                break;
            case MOORLANDS_LAMB:
                pieChartDataRef.current = getSpeciesClassesSummaryWithinDateRange(MoorlandsPieChartData, sliderDates[0], sliderDates[1],reportFilters.class_name);
                barChartDataRef.current = getSpeciesClassesWithinDateRange(MoorlandsPieChartData, sliderDates[0], sliderDates[1],reportFilters.class_name);
                treeMapDataRef.current = getTreeMapDataFromFeatureCollection(MoorlandsSpeciesData as FeatureCollection,sliderDates[0], sliderDates[1], reportFilters.class_name);
                break;
            default:
                pieChartDataRef.current = [];
                barChartDataRef.current = [];
                treeMapDataRef.current = [];
        }
    },[selectedOrganisation, sliderDates, reportFilters.class_name]);

    // 渲染图表时直接使用ref.current
    return (
        // ... 保留原有结构
        <Treemap
            data={treeMapDataRef.current}
            // ... 其他属性不变
        >
            {
                treeMapDataRef.current.map((entry, index) => (
                   <Cell key={`cell-${index}`}
                         fill={CHART_FILL_COLOURS.find(color => color.dataKey == entry.name)?.fill} />
            ))}
            <Tooltip />
        </Treemap>
        // ...
    )
}

2. 使用useMemo缓存计算结果

如果数据需要根据状态动态计算且计算开销较大,useMemo可以缓存计算结果,只有当依赖项变化时才重新计算,同时返回的值可直接用于渲染,避免不必要的重复计算。

示例:

export default function Page(){
    // ... 保留原有状态定义

    const chartData = React.useMemo(() => {
        let pieData: any[] = [];
        let barData: any[] = [];
        let treeMapData: any[] = [];

        switch (selectedOrganisation) {
            case ALUAN_COCONUTS:
                // 对应企业的数据处理逻辑
                break;
            case BLANEY_FARM:
                // 对应企业的数据处理逻辑
                break;
            case MOORLANDS_LAMB:
                pieData = getSpeciesClassesSummaryWithinDateRange(MoorlandsPieChartData, sliderDates[0], sliderDates[1],reportFilters.class_name);
                barData = getSpeciesClassesWithinDateRange(MoorlandsPieChartData, sliderDates[0], sliderDates[1],reportFilters.class_name);
                treeMapData = getTreeMapDataFromFeatureCollection(MoorlandsSpeciesData as FeatureCollection,sliderDates[0], sliderDates[1], reportFilters.class_name);
                break;
            default:
                // 默认空数据
        }

        return { pieData, barData, treeMapData };
    }, [selectedOrganisation, sliderDates, reportFilters.class_name]);

    // 渲染时使用chartData中的对应数据
    return (
        // ... 保留原有结构
        <Treemap
            data={chartData.treeMapData}
            // ... 其他属性不变
        >
            {
                chartData.treeMapData.map((entry, index) => (
                   <Cell key={`cell-${index}`}
                         fill={CHART_FILL_COLOURS.find(color => color.dataKey == entry.name)?.fill} />
            ))}
            <Tooltip />
        </Treemap>
        // ...
    )
}

3. 拆分图表子组件

将每个图表封装成独立子组件,把依赖项(selectedOrganisation、sliderDates等)作为props传入,子组件内部处理数据计算。这样父组件重渲染时,只有当子组件的props变化时才会重新计算数据,减少不必要的计算开销,同时提升代码可维护性。

示例子组件:

interface TreeMapChartProps {
    selectedOrg: string;
    sliderDates: number[];
    reportFilters: any;
}

const TreeMapChart = ({ selectedOrg, sliderDates, reportFilters }: TreeMapChartProps) => {
    const treeMapData = React.useMemo(() => {
        if (selectedOrg === MOORLANDS_LAMB) {
            return getTreeMapDataFromFeatureCollection(MoorlandsSpeciesData as FeatureCollection,sliderDates[0], sliderDates[1], reportFilters.class_name);
        }
        // 其他企业的处理逻辑
        return [];
    }, [selectedOrg, sliderDates, reportFilters.class_name]);

    return (
        <div className="treemap-chart-wrapper">
             <Treemap
                width={500}
                height={250}
                data={treeMapData}
                isAnimationActive={false}
                nameKey="name"
                dataKey="size"
                type="nest"
                nestIndexContent={item => {
                    return <div>{`${item.name || 'root'}`}</div>;
                }}
            >
                {
                    treeMapData.map((entry, index) => (
                       <Cell key={`cell-${index}`}
                             fill={CHART_FILL_COLOURS.find(color => color.dataKey == entry.name)?.fill} />
                ))}
                <Tooltip />
            </Treemap>
            <p>Relative composition of species by type</p>
        </div>
    );
};

// 父组件中使用
export default function Page(){
    // ... 保留原有状态定义
    return (
        // ... 保留原有结构
        <Grid item xs={6} md={6}>
            <TreeMapChart 
                selectedOrg={selectedOrganisation} 
                sliderDates={sliderDates} 
                reportFilters={reportFilters} 
            />
        </Grid>
        // ...
    )
}

方案选择建议

  • 如果数据仅用于图表展示、不需要触发全局UI重渲染,优先选useRef;
  • 如果数据需要根据状态动态计算且要缓存结果,选useMemo;
  • 如果图表数量多、逻辑复杂,拆分组件更利于维护和性能优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:15:53