多个反应组件实例无法正常工作?

时间:2016-10-10 14:58:54

标签: javascript reactjs

我试图创建反应组件的多个实例,但只渲染了第一个实例。我想我在这里做了一些重大的失败:)

这是组件。



import React from 'react';
import ReactDOM from 'react-dom';
import ChartJS from 'chart.js'
import DataService from '../core/data-service.js';

function GetReportData() {

    let chartElement = document.getElementById('react-chart-bar');

    var id = {
        id: chartElement.dataset.id
    };

    DataService.getReportData(id).done(function(data) {
        renderChart(data);
    }).fail(function(jqXHR, status, error) {
        console.log(error);
    });
}

function renderChart(data) {

    var ctx = document.getElementById('chart-bar');

    var chart_bar = new ChartJS(ctx, {
        type: data.ChartType,
        data: {
            labels: data.Labels,
            datasets: data.DataSet
        },
        options: {
            responsive: true,
            scales: {
                yAxes: [
                    {
                        ticks: {
                            beginAtZero: true,
                            max: data.MaxTicks
                        }
                    }
                ]
            }
        }
    });
}


class Chart extends React.Component {
    componentDidMount() {
        GetReportData();
    }
    render() {
        return <div>
            <canvas id="chart-bar" width="400" height="300"></canvas>
        </div>
    }
}

let node = document.getElementById('react-chart-bar');

if (node != null) {
    ReactDOM.render(
        <Chart/>, node);
}
&#13;
&#13;
&#13;

然后在我的HTML中,我调用这样的组件。

&#13;
&#13;
<div id="react-chart-bar" data-id="1"></div>
<div id="react-chart-bar" data-id="9"></div>
&#13;
&#13;
&#13;

我需要渲染相同的组件,但基于HTML元素的data-id属性使用不同的数据。

感谢您的帮助:)

// G

2 个答案:

答案 0 :(得分:0)

不要像使用其他框架那样使用id属性,而是在React组件中使用ReactDOM.findDOMNode来获取对真实DOM节点的引用。仅在已经渲染组件时执行此操作,例如在componentDidMount内部:

import React from 'react';
import ReactDOM from 'react-dom';
import ChartJS from 'chart.js'
import DataService from '../core/data-service.js';


class Chart extends React.Component {
    componentDidMount() {
        let chartElement = ReactDOM.findDOMNode(this);

        var id = {
            id: this.props.reportId,
        };

        DataService.getReportData(id).done((data) => {
            this.renderChart(data);
        }).fail(function(jqXHR, status, error) {
            console.log(error);
        });
    }
    renderChart(data) {
        var ctx = ReactDOM.findDOMNode(this);

        var chart_bar = new ChartJS(ctx, {
            type: data.ChartType,
            data: {
                labels: data.Labels,
                datasets: data.DataSet
            },
            options: {
                responsive: true,
                scales: {
                    yAxes: [
                        {
                            ticks: {
                                beginAtZero: true,
                                max: data.MaxTicks
                            }
                        }
                    ]
                }
            }
        });
    }
    render() {
        return <div>
            <canvas width="400" height="300"></canvas>
        </div>
    }
}

let node = document.getElementById('react-chart-bar');

if (node != null) {
    ReactDOM.render(
        <Chart reportId={node.getAttribute('data-id')} />,
        node
    );
}

答案 1 :(得分:0)

我建议使用包装器组件,并为每个id呈现如下图表。

&#13;
&#13;
function getReportData(id) {
    return `Here is some data for id ${id}`;
}

class Chart extends React.Component {
    constructor () {
      super();
      
      this.state = {
        data: null
      };
    }

    componentDidMount() {
        this.setState({ data: getReportData(this.props.dataId) });
    }
  
    render() {
        return (
          <div>
            <span>{this.state.data}</span>
            <canvas id="chart-bar" width="400" height="10"></canvas>
          </div>
        );    
    }
}

class App extends React.Component {
    render() {
        return (
          <div>
            <Chart dataId='1' />
            <Chart dataId='2' />
          </div>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'></div>
&#13;
&#13;
&#13;