0

I have a React component that renders an SVG and plots lines like so.

class Parent extends React.Comoponent {
    constructor(props) {
        super(props)
        this.state = {
            dataset1: [[1, 2, 3], [4, 5, 6]],
            dataset2: [[6, 5, 4], [3, 2, 1]]
        }
        render() {
            return <LineChart dataset1={this.state.dataset1} dataset2={this.state.dataset2} />
     }
}
class LineChart extends React.Component {

    render() {
        return (
            <svg>
               { this.props.dataset1.map( d => {
                   return <Line data=d />
               })
               {
                  this.props.dataset2.map( d => {
                    return <Line data=d />
               })
             }
             </svg>
        )
    }
}

Now I need to add a third dataset, and I could continue to pass them to LineChart and modifify LineChart to handle them, but that seems cumbersome and bad for reusability, so I was hoping to find a solution that looks something more like this:

class LineChart extends React.Component {
    render() {
        return(
            <svg> 
                { this.props.dataset.map( d=> { return <Line data=d /> }) }
            </svg>
     }
}
<LineChart dataset={this.state.dataset1} />
<LineChart dataset={this.state.dataset2} />

or

<LineChart >
    { this.state.dataset1.map( d => { return <Line data=d /> }) }
    { this.state.dataset2.map( d => { return <Line data=d /> }) }
</LineChart>

Where both datasets still end up on the same svg?

I think I've seen this syntax but not sure how to implement it. I did try searching an answer but I've had a hard time finding the phrase to search for. Thank you!

* EDIT * Thank you @yonghoo noh and @gaurav Bhusare for your answers. If this is the best way then this is what I'll do, but is there a way I could use the props.children property?

The reason being is each set of lines has associated parameters, styling, and ability to update dynamically, and I want to avoid restructuring the data of all these objects.

I revised a post from this question How to pass in a react component into another react component to transclude the first component's content? to ask if I can apply this to my case.

const LineChart = ({children}) => (
  <svg>
    {children}
  </svg>
);

const Plot = () => {
    <LineChart />
        <Line data=dataset1 />
        <Line data=dataset2 />
    </LineChart>
}
sin tribu
  • 1,148
  • 1
  • 6
  • 14

2 Answers2

1
class Parent extends React.Comoponent {
    constructor(props) {
        super(props)
        this.state = {
            dataSets:[[[1, 2, 3], [4, 5, 6]],[[6, 5, 4], [3, 2, 1]]]

        }
        }
    render() {
         return <LineChart datasets={this.state.dataSets}/>
    }
}
class LineChart extends React.Component {

render() {
    return (
        <svg>
           {this.props.dataSets.map(data=>{
           data.map(d=>{
                return <Line data={d} />
           })
           })}

         }
         </svg>
    )
}

}

Gaurav Bhusare
  • 195
  • 1
  • 17
0

Since you've used state(could be changed), I think this is more performant way:

class Parent extends React.PureComponent {
    constructor(props) {
        super(props)

        this.state = {
            datasets: [[[1, 2, 3], [4, 5, 6]], [[6, 5, 4], [3, 2, 1]]]
        }
    }

    render() {
        return (
            <>
                { this.state.datasets.map((dataset, idx) =>
                    <LineChart key={idx} dataset={dataset} />) }
            </>
        )
    }
}

class LineChart extends React.PureComponent {
    render() {
        return (
            <svg>
                { this.props.dateset.map((data, idx) => <Line data={data} key={idx} />) }
            </svg>
        )
    }
}

By using React.PureComponent instead of React.Component, when an element of the datasets array is changed, only one LineChart component corresponding to the element will be re-rendered. The other LineChart components will not be re-rendered.

Yonggoo Noh
  • 1,811
  • 3
  • 22
  • 37