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

React-Grid-Layout中多Highcharts无法同步随网格缩放的问题求助

Hey there! Let's figure out why only one of your Highcharts is resizing with the grid, and fix this so all charts sync up properly.

The Root Cause

The problem boils down to shared React refs in your code. You're using this.conRef and this.myRef for every grid item in your map loop. Each time the loop runs, it overwrites these refs with the latest item—so by the end, only the last grid's container and chart are referenced. That's why only that one chart responds to resizing.

Solution 1: Use a Ref Array to Track Each Chart

We'll create an array to store unique refs for every grid container and its chart, then target the specific chart when its grid is resized.

Here's the updated code:

import React, { Component } from "react";
import { Responsive, WidthProvider } from "react-grid-layout";
import HighchartsReact from "highcharts-react-official";
import Highcharts from "highcharts/highstock";
import "./styles/styles.css";

const ResponsiveGridLayout = WidthProvider(Responsive);

// Keep your data and config definitions here...

export default class App extends Component {
  constructor(props) {
    super(props);
    // Initialize an array to hold refs for each grid item
    this.gridRefs = [];
  }

  handleResizeStop = (_, layoutItem) => {
    // Find the ref matching the resized grid's ID
    const target = this.gridRefs.find(ref => ref.id === layoutItem.i);
    if (target) {
      const { containerRef, chartRef } = target;
      if (chartRef.current && containerRef.current) {
        // Update the chart size to match its container
        chartRef.current.chart.setSize(
          containerRef.current.clientWidth,
          containerRef.current.clientHeight
        );
      }
    }
  };

  render() {
    const gridItems = [
      { id: "1", name: "Item One" },
      { id: "2", name: "Item Two" }
    ];
    const layout = [
      { i: "1", x: 0, y: 0, w: 2, h: 1, minW: 2, minH: 1 },
      { i: "2", x: 5, y: 0, w: 2, h: 1, minW: 2, minH: 1 }
    ];

    // Clear refs before re-rendering to avoid duplicates
    this.gridRefs = [];

    return (
      <ResponsiveGridLayout
        layouts={{ lg: layout }}
        measureBeforeMount={true}
        className="layout"
        isDraggable={true} // Fixed typo: was isDragable
        isResizable={true}
        margin={[20, 20]}
        onResizeStop={this.handleResizeStop}
      >
        {gridItems.map((item) => {
          // Create unique refs for each grid container and chart
          const containerRef = React.createRef();
          const chartRef = React.createRef();
          this.gridRefs.push({ id: item.id, containerRef, chartRef });

          return (
            <div key={item.id} ref={containerRef} className="grid-item">
              <HighchartsReact
                ref={chartRef}
                containerProps={{ style: { width: "100%", height: "100%" } }}
                options={config}
                highcharts={Highcharts}
              />
            </div>
          );
        })}
      </ResponsiveGridLayout>
    );
  }
}

Solution 2: Create a Reusable Grid Item Component (More Modular)

For a cleaner, more maintainable approach, wrap each chart in its own component that handles resizing internally using ResizeObserver. This way, you don't need to manage refs in the parent component at all.

First, create ChartGridItem.jsx:

import React, { useEffect, useRef } from "react";
import HighchartsReact from "highcharts-react-official";
import Highcharts from "highcharts/highstock";

const ChartGridItem = ({ options }) => {
  const containerRef = useRef(null);
  const chartRef = useRef(null);

  useEffect(() => {
    // Watch for container size changes
    const observer = new ResizeObserver((entries) => {
      entries.forEach(entry => {
        const { width, height } = entry.contentRect;
        if (chartRef.current) {
          chartRef.current.chart.setSize(width, height);
        }
      });
    });

    if (containerRef.current) {
      observer.observe(containerRef.current);
    }

    // Clean up observer on unmount
    return () => {
      if (containerRef.current) {
        observer.unobserve(containerRef.current);
      }
    };
  }, []);

  return (
    <div ref={containerRef} className="grid-item">
      <HighchartsReact
        ref={chartRef}
        containerProps={{ style: { width: "100%", height: "100%" } }}
        options={options}
        highcharts={Highcharts}
      />
    </div>
  );
};

export default ChartGridItem;

Then update your main App.jsx:

import React, { Component } from "react";
import { Responsive, WidthProvider } from "react-grid-layout";
import ChartGridItem from "./ChartGridItem";
import "./styles/styles.css";

const ResponsiveGridLayout = WidthProvider(Responsive);

// Keep your data and config definitions here...

export default class App extends Component {
  render() {
    const gridItems = [
      { id: "1", name: "Item One" },
      { id: "2", name: "Item Two" }
    ];
    const layout = [
      { i: "1", x: 0, y: 0, w: 2, h: 1, minW: 2, minH: 1 },
      { i: "2", x: 5, y: 0, w: 2, h: 1, minW: 2, minH: 1 }
    ];

    return (
      <ResponsiveGridLayout
        layouts={{ lg: layout }}
        measureBeforeMount={true}
        className="layout"
        isDraggable={true}
        isResizable={true}
        margin={[20, 20]}
      >
        {gridItems.map((item) => (
          <ChartGridItem key={item.id} options={config} />
        ))}
      </ResponsiveGridLayout>
    );
  }
}

Quick Notes

  • I fixed a typo in your original code: isDragable → isDraggable (that's the correct prop name for react-grid-layout)
  • If you need to support older browsers, add a polyfill for ResizeObserver (Solution 2)
  • Solution 2 is better for scalability—adding more charts later won't require changing the parent component logic

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:54:10