Simple Data Visualization in React — Learn how to build a progress meter

Learn how to use React + SVG rectangles to visualize progress in a React application

Brandon Morelli
codeburst

--

Rectangles. Photo by Samuel Zeller

Preface

Last month I attended a ReactJS Boston meetup on Data Visualization Strategies in React. The presenter was Adam Mark, a UI Engineer for MC10. Adam shared some really cool and intricate stuff, but also shared a very simple progress meter he built in React using two SVG rectangles. It’s unbelievably simple, yet clean and elegant.

If you just want the code and want to skip the tutorial, all of the code for the React Meter Component is available on Adam’s GitHubGist.

What we’ll be building

Data progress meters with varying colors, shapes, sizes and animations:

If this tutorial interests you, I strongly recommend you check out my 3 Best React JS Courses where you can learn to build some larger scale, (really cool) real-world react applications!

The SVG Code

Our react component will dynamically create the SVG code based on the input variables. Here’s an example of what the SVG code might look like for one of the meters:

<svg width="100" height="10">
<rect width="100" height="10" fill="#ccc" rx="0" ry="0"></rect>
<rect width="20" height="10" fill="#0078bc" rx="0" ry="0"></rect></svg>

That’s it.

It’s one svg object with two rect (rectangles). The first rectangle is 100px wide and grey. Rendered on top of that rectangle is a smaller blue rectangle that is only 20px wide. Here’s what it looks like:

woah, progress meter, so cool

Simply rendering one colored rectangle on top of one grey rectangle results in a pretty cool looking progress meter!

But how do we create this code dynamically? That’s where react comes in. We’re going to send all the data via props to a React Component which will then render the correct rectangles.

React Project Setup

For this project we’ll be using create-react-app , To scaffold out a boilerplate react app you can run:

create-react-app react-svg-meter
cd react-svg-meter
npm start

Once your server starts, you’ll be able to navigate to http://localhost:3000/ and see the boilerplate code in action.

Now the fun begins. Create a file in the src directory named Meter.js , import react, and export a function named Meter. In our Meter function, we’ll simply return <div>test</div> for now.

import React from 'react';var Meter = function (props) {
return(
<div>test</div>
);
}
export default Meter;

We can now import this function into our app.js file:

import Meter from './Meter';

And finally, we can change the return statement in app.js to return our Meter component:

return (
<div className="App">
<Meter />
</div>
);

Awesome. Step one complete! You should be able to see the word ‘test’ in your browser when you navigate to http://localhost:3000/

Meter.js

Meter.js is where all the magic happens… but it’s not magic, it’s actually quite simple. First, were going to set some default props:

var Meter = function (props) {
var {
percent = 0, // number: 0 - 1, inclusive. Fill %
width = 100, // the width of our meter
height = 10, // the height of our meter
rounded = true, // if true, use rounded corners
color = "#0078bc", // the fill color
animate = false, // if true, animate
label = null // a label for accessibility
} = props;
//...
}

The comments should make it pretty clear what each of these props do. Now, we can use the props to dynamically create and return our SVG meter!

Recall our earlier code with a 20% full, blue meter:

<svg width="100" height="10">
<rect width="100" height="10" fill="#ccc" rx="0" ry="0"></rect>
<rect width="20" height="10" fill="#0078bc" rx="0" ry="0"></rect></svg>

What we’re going to do is replace the hard-coded values with variables, and return the SVG element. Here’s what that looks like:

return (
<svg width={width} height={height} aria-label={label}>
<rect width={width} height={height} fill="#ccc" rx={r} ry={r}/>
<rect width={w} height={height} fill={color} rx={r} ry={r} style={style}/>
</svg>
);

As you can see there are a couple variables we need to do some math for: r, w, and style.

  • r — Creates our rounded corners (if necessary):
var r = rounded ? Math.ceil(height / 2) : 0;
  • w — Calculates the width of our colored rectangle (giving the meter effect):
var w = percent ? Math.max(height, width * Math.min(percent, 1)): 0;
  • style —Animates the meter (if necessary):
var style = animate ? { "transition": "width 500ms, fill 250ms" } : null;

We now have a Meter component that will dynamically return an SVG object based on input props. If no props are sent, the component will default and send back a grey meter that is 0% full.

Sending information from app.js

Now all that’s left is to pass in the data from app.js. Here’s an example of what our code would look like in app.js to create varying progress meters:

// default, empty meter
<Meter />
// 80%, rounded
<Meter percent={.8} />
// 60%, rectangle
<Meter percent={.6} rounded={false} />
// 40%, custom size, rectangle
<Meter percent={.4} width={250} height={17} rounded={false} />

Links to Code:

  • View Meter.js on Adam’s Gist.
  • View the full React application with Meter.js in use on my GitHub Repo.
  • View the demo on Codepen.

You did it!

And that’s some simple data visualization with React! I publish a few articles and tutorials each week, please consider entering your email here if you’d like to be added to my once-weekly email list.

If tutorials like this interest you and you want to learn how to build more cool stuff with React, check out the 3 Best React JS Courses.

If this post was helpful, please click the clap 👏button below a few times to show your support! ⬇⬇

--

--

Creator of @codeburstio — Frequently posting web development tutorials & articles. Follow me on Twitter too: @BrandonMorelli