【问题标题】:React prop gets overwritten when using highcharts?使用 highcharts 时 React 属性被覆盖?
【发布时间】:2020-11-02 22:43:22
【问题描述】:

我有一个接收两个输入的反应组件:数据和规范化器。

<ChartInterface
      normalizer={[10, 10, 10, 10]}
      data={[
        { name: "lineA", data: [2, 1, 1, 2] },
        { name: "lineB", data: [1, 0, 3, 0] }
      ]}
    />

ChartInterface 组件应该呈现一个复选框和一个图表;当未选中该复选框时,它应该只呈现一个包含数据的图表,效果很好;如果选中该复选框,则组件应将所有data 数组除以normalizerarray,我已经编写了这样做的函数。

但是,问题是当我反复选中和取消选中此复选框时,数据会一遍又一遍地被数组分割。

仅当我添加 &lt;HighchartsReact options={chartOptions} highcharts={Highcharts} /&gt; 组件时才会出现此问题,如果我将其注释掉并仅打印 chartOptions.lineData 复选框将按预期工作。 (选中复选框显示标准化数据,取消选中显示原始数据,因为它是作为道具提供的)

ChartInterface 组件:

const ChartInterface = (props) => {
  // state for checkbox if chart needs to be normalized or not
  const [isNormalized, setIsNormalized] = useState(false);

  //divides one array by another, element-wise
  function normalize(a, b) {
    return a.map(function (x, idx) {
      return x / b[idx];
    });
  }

  // get data for lines
  let lineData = props.data;

  //if normalized is checked, normalize the data
  if (isNormalized) {
    lineData = lineData.map((line) => {
      return {
        name: line.name,
        data: normalize(line.data, props.normalizer)
      };
    });
  }

  // Chartoptions for highcharts, here we add the line data
  const chartOptions = {
    chart: { type: "area" },
    xAxis: {
      type: "category",
      crosshair: true
    },
    plotOptions: {
      area: {
        stacking: "normal",
        lineWidth: 1
      }
    },
    series: lineData
  };

  return (
    <>
      <input
        type="checkbox"
        checked={isNormalized}
        onChange={(e) => setIsNormalized(e.target.checked)}
      />
      Normalise the data ?
      {<HighchartsReact options={chartOptions} highcharts={Highcharts} />}
      {JSON.stringify(lineData)}
    </>
  );
};

我还制作了一个代码沙箱示例,您可以通过选中和取消选中复选框轻松查看问题所在:codesandbox demo of problem 谢谢你的帮助

【问题讨论】:

    标签: javascript reactjs highcharts


    【解决方案1】:

    尝试通过更新状态来更改您的数据。怎么做你可以在这里找到:https://stackblitz.com/edit/react-6qlksy?file=index.js

    【讨论】:

    • 非常感谢,我在尝试将其用作状态时似乎遗漏了一些东西
    【解决方案2】:

    查看此更新的codesandbox 链接。出于某种原因,Highcharts 正在改变您的lineData。可能有更好的方法,但是通过使用 lodash 的 cloneDeep,您可以看到在传递给 Highcharts 选项之前对数据进行深层复制时它可以工作。

    【讨论】:

      【解决方案3】:

      所以你的实际问题在于在第一次渲染时将 props.data 的引用传递给 chartOptions.series(当复选框被禁用时):

      let lineData = props.data
      

      在这里你复制 props.data 的引用,然后你不要改变它,因为你的 If 是 ingored 然后你创建 chartOptions,其中 series = props.data。 因此,当您将 Highchars series 引用到您的 props.data 时 - 当您更改一个时 - 您会更改另一个。

      现在很好的问题是,为什么稍后重新渲染该引用不会被新对象覆盖,而是 Highchart 正在改变初始对象。 事实证明这是 Highchart 组件优化,仔细查看他们的代码 (https://github.com/highcharts/highcharts-react/blob/master/src/HighchartsReact.js) 你会发现他们没有重新创建组件,而是他们正在执行 chartRef.current.update 轮到不是简单地说options = newOptions,而是逐个属性地改变初始对象,如果在上面看你的初始对象实际上是你自己的props.data

      要解决这个问题,您需要对 props.data 进行深层复制,而不是像 Charlies 在上一个答案中所建议的那样只使用 lineData = props.data

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-19
        • 1970-01-01
        • 1970-01-01
        • 2015-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-19
        相关资源
        最近更新 更多