【问题标题】:Deleting and recreating an element with React使用 React 删除和重新创建元素
【发布时间】:2015-12-29 07:21:47
【问题描述】:

我正在尝试让 Chart.js 与 React.js 一起工作,我已经接近了。

我让 React 渲染了正确的图表,当我改变状态时,新图表被绘制在另一个图表之上。问题是悬停事件显然留在了canvas 上,将鼠标移到它上面会闪现之前制作的所有版本的图表。

据我所知,这是 Chart.js 中的一个错误,解决方案是删除 canvas 元素并用新的画布元素替换它。

所以我有这段代码,它可以在页面上获取图表:

var LineChart = React.createClass({
  render: function() {
    return (
      <div id="lineHolder" className="graphHolder">
        <h2 className="sectionHeader">Earnings per day</h2>
        <canvas id="lineChart" width="688" height="286"></canvas>
      </div>
    );
  },
  ctx: {},
  lineChart: {},
  componentDidMount: function() {
    this.drawChart();
  },
  componentDidUpdate: function() {
    this.drawChart();
  },
  drawChart: function() {
    var lineData = {
      labels: this.props.dates,
      datasets: [{
        label: "Earnings",
        fillColor: "rgba(151,187,205,0.2)",
        strokeColor: "rgba(151,187,205,1)",
        pointColor: "rgba(151,187,205,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(151,187,205,1)",
        data: this.props.earnings,
      }]
    }
    this.ctx = document.getElementById("lineChart").getContext("2d");
    this.lineChart = new Chart(this.ctx).Line(lineData);
  }
});

但我想不出“反应方式”来删除和替换该画布元素,每次需要重绘时。

有什么想法吗?

【问题讨论】:

  • 在分配值之前,你认为像 $("lineChart").empty() 这样清空画布是什么意思
  • @dhavalpatel,这个应用程序现在没有 jQuery。我可能会在稍后添加它,但如果可能的话,我想将这部分保留为 React.js 的样式
  • document.getElementById("lineChart").innerHTML = "";
  • 不要使用像innerHTML这样的直接DOM操作方法。

标签: javascript html canvas reactjs chart.js


【解决方案1】:

在 React 中,您希望在每次道具或状态更改时更改视图。如果您使用的是 DOM 操作库,例如 Chart.js,那么 React 生命周期方法就派上用场了。

https://facebook.github.io/react/docs/component-specs.html

您可以使用componentWillUpdatecomponentDidUpdate(取决于适合的情况)将下一个状态与上一个状态进行比较。

componentWillUpdate(nextProps, nextState) {
    /* Optionally include logic comparing nextProps or nextState
     * to this.props or this.state
     */
    this.lineChart.clear();
}

只要确保是道具/状态的变化推动了图表的变化。

我对这个明显的 Chart.js 错误知之甚少。但如果您确实需要每次都重新渲染 canvas 元素,我建议您在 canvas 元素上放置一个key 属性。

<canvas key={this.uniqueKey()} id="lineChart" width="688" height="286"></canvas>

this.uniqueKey() 产生的东西很难说。但是每次 props 或 state 改变时它都需要不同。只有在Chart#clear()(或Chart#destroy())等更简单的方法失败时才使用此方法。

【讨论】:

  • 看看,破坏成功了!感谢您查看这个。出于好奇,Math.random() 会是一个可接受的键,还是会触发一些可怕的事情?
  • Math.random() 不是一个足够好的密钥,因为它不幸的非唯一性。参考facebook.github.io/react/docs/reconciliation.html的底部@一个可预测的递增数字可能会更好。
  • 所以我不得不为每个画布元素添加一个计数器。我在应用程序中有多个“选项卡”,当您从选项卡切换回它时,需要重新启动画布。我需要担心这会影响性能吗?我能想到的唯一其他选择是在每次选项卡更改时重新渲染整个选项卡,这似乎更糟。
【解决方案2】:

试试这个 -

var LineChart = React.createClass({
  render: function() {
    return (
      <div id="lineHolder" className="graphHolder">
        <h2 className="sectionHeader">Earnings per day</h2>
        <canvas ref="lineChart" key={this.state.canvasUpdateToggle} width="688" height="286"></canvas>
      </div>
    );
  },
  ctx: {},
  lineChart: {},
  getInitialState:function(){
    return {canvasUpdateToggle:"0"};
  },
  componentDidMount: function() {
    this.drawChart();
  },
  componentDidUpdate: function() {
    this.drawChart();
  },
  componentWillReceiveProps:function(){
    var canvasUpdateToggle = this.state.canvasUpdateToggle == 0? 1: 0;
    this.setState({"canvasUpdateToggle":canvasUpdateToggle});
  },
  drawChart: function() {
    var lineData = {
      labels: this.props.dates,
      datasets: [{
        label: "Earnings",
        fillColor: "rgba(151,187,205,0.2)",
        strokeColor: "rgba(151,187,205,1)",
        pointColor: "rgba(151,187,205,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(151,187,205,1)",
        data: this.props.earnings,
      }]
    }
    this.ctx = this.refs.lineChart.getContext("2d");
    this.lineChart = new Chart(this.ctx).Line(lineData);
  }
});

【讨论】:

    猜你喜欢
    • 2020-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多