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>
}

2 Answers 2

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>
    )
}

}

Sign up to request clarification or add additional context in comments.

Comments

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.

1 Comment

I don't have the rep to do anything but comment and say thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.