ReactJS and SVG — Part Two

Representing dynamic data using React and SVG — Multiple Graphics for Relational Data

Jacob Fletcher
TRBL
Published in
4 min readMar 20, 2018

--

This is part two of three on creating a visual representation of dynamic data. In the first part, we simply generated an SVG-based line graph from a single array of values. In this part, we’ll learn how to enhance our component to handle multiple datasets as opposed to just one.

For your convenience, I’ve created a GitHub repository for each part in this series. I’d encourage you to clone this project into your local environment and get familiar with it before continuing on.

This part is a direct progression from the last, so read it!

From a single line graph, to many.

Getting Right To it!

The Premise

At this point, we’ve got a single line graph being programmatically generated from a single array of numbers in which the client has control over. Now, we will manipulate this logic to handle more than just a single dataset, but many. So what we need to do first is create a tab-style navigation that the user can interact with, and then update our SVG according to which tab is selected.

So first things first, we need to find a new home for our client’s data. Previously, we had defined a variable within the constructor of our component called this.arrayY, but now its appropriate for this to live inside of the component’s state — we’ll need to group it with other associative data, such as a label and whether or not its currently active, and then re-render the component based on this status. I went ahead and generated some dummy data to simulate the client:

this.state = {
menu: [
{
label: "Graph 1",
active: false,
array: [5, 30, -5, -10, 15, -15, 20, 5, 8, -12, -20, 2, 3, -5, 8, -2, 22, -30, -22]
}, {
label: "Graph 2",
active: true,
array: [30, 25, 35, 15, 25, 17, 20, -5, 12, 7, -28, 2, -30, -20, -22, -2, -27, -30, -35]
}, {
label: "Graph 3",
active: false,
array: [-12, -35, -28, -30, -7, -1, -22, 16, 2, -5, 4, -19, -2, 15, 10, 25, 30, 28, 35]
}, {
label: "Graph 4",
active: false,
array: [5, 12, -2, 8, 3, -12, 20, 5, 8, -12, -20, -9, 5, 12, -1, -2, 22, -30, 5]
}
]
}

The Navigation

Now that we have established our new data structure and place-held some dummy data, we’ll leverage a <ul/> as our navigation so the user can toggle this data at-will. Our JSX markup should look something like this now:

<div className="chart">
<ul className="chart-header">
{this.state.menu.map((item, i) => {
const active = item.active ? 'menu-item active' : 'menu-item';
return (
<li key={i} className={active}>
<button onClick={() => this.handleClick(i)}>
{item.label}
</button>
</li>
)
})}
</ul>
<div className="chart-body">
<Graph
arrayX={this.arrayX}
arrayY={this.state.menu[this.currentIndex].array}
polyline={this.polyline}
/>
</div>
</div>

And of course, we’ll need a function to handle the click event, and perform all of the heavy lifting. Remember to keep state immutable:

handleClick(key) {
this.currentIndex = key;
this.generatePolylineArray();
const newState = [...this.state.menu]; for (var i = 0; i < newState.length; i++) {
if (newState[i].active) {
newState[i].active = false;
}
}
newState[key].active = true;
this.setState({newState});
}

With Style

What we have so far works, but it doesn’t look like much. Let’s go ahead and add some logic to check the current index of our navigation and add a semantic class based on that index. We’ll do this right inside of our render function:

const color = this.currentIndex === 0 ? 'blue'
: this.currentIndex === 1 ? 'orange'
: this.currentIndex === 2 ? 'red'
: this.currentIndex === 3 ? 'green'
: ''

And of course, our top-level <div> should be set up to accept this class:

<div className={`chart ${color}`}>
[...]

The Graph

We don’t even need to touch this component, good work!

Part two: check.

We’ve come along way, but there is still room for improvement. Next, we’ll add some animation to help improve usability.

Thanks for reading! If you found value in this series whatsoever, please applaud or even comment — I’d love to chat.

Or on the off-chance you’re feeling burned out from this topic, check out James Mikrut’s post about our studio’s new website. I know your time is valuable but you have my word, this is a great way to spend it.

--

--