Welcome to the third installment in our series on Data Visualization with Progress KendoReact. We created a dynamic layout within our single-page React application using KendoReact’s layout functionality.Image may be NSFW.
Clik here to view.
Today we’ll be taking a step away from the view and working on, arguably, the most important part of our application: the data itself. KendoReact is quite intelligent at guessing how we want to display data. However, we still need to do some significant manipulation of our raw data to shape it into something that KendoReact’s data visualization components can use. Today our main focus will be on how to pull out information from JSON data based on business specifications. We’ll use building blocks like higher-order functions and mapping/reducing to accomplish this.
Here’s the general shape of the data that we’ll be teasing apart:
[
{
name: string representing region,
restaurants: [
{
name: string representing individual store,
ratings: [
{
date: string representing review sample time,
values: {
customer: string,
staff_satisfaction: string,
sales: string,
cleanliness: string
}
},
...
]
},
...
]
},
...
]
The JSON data above represents several regions of stores and the ratings that each store has received. I’ve written a set of utility functions for splitting this data apart and getting everything we need to visualize the data. Today I’ll mainly be talking about loading in the data. Then I’ll demonstrate one of the functions that’s being used throughout these data manipulations.
The first thing we have to do in our application to work with this data is actually import it. In a real-world application, that would likely mean fetching asynchronously from a backend or external source, but for now we’ll import the rating data statically. Let’s add these two lines to our App.js
file. The first in the outer scope with the rest of our imports and the second within the definition of our App
component:
import ratingsJSON from './data/pizza-store-data.json';
...
const [ratings] = useState([{ name: 'All Regions' }, ...ratingsJSON]);
In the above example, we’re loading in the rating data via useState
. Since we want the data to be our primary source of truth, we won’t destructure out the second mutative argument from useState
‘s return value. If you’re confused about the useState
call here, check out our previous installment that goes over using React Hooks to setup local application state.
A critical principle of ReactJS and many front-end frameworks is the idea that the view is simply a projection or representation of an application’s state. Any time the data changes, the view shows that new state faithfully.
As such, we’ll want to do any data operations separate from the view. Let’s make a directory in src/
called utils/
and include a file to do all of our data operations. I named mine dataSplitter.js
.
Image may be NSFW.
Clik here to view.
For the remainder of this article I’m going to discuss one of the main building blocks that dataSplitter
uses. All of the operations that I’m performing on this data are built from a few basic ideas and I’m hoping that if I describe this one example, you’ll be able to parse out many of the tools that I’m creating within dataSplitter
.
Note: The rest of article assumes you have a pretty good understanding of JavaScript array map
and reduce
methods among others. If you need to brush up you knowledge of these concepts before continuing, I suggest this article that follows a similar philosophy for how I’ll be manipulating our ratings data.
Pluck
One extremely beneficial pattern for destructuring JSON data in JavaScript is commonly referred to as pluck
. Pluck is a higher-order function that gets properties off of an object. You might be wondering: “Why can’t we just access object properties with dot notation?”. For one, this can be dangerous and cause a program to crash if you attempt to access a property that isn’t there. Destructuring objects can avoid this with defaulting, but the notation can be quite confusing and less transferrable between problems. A pluck pattern solves these problems and allows us to grab properties from deep within JSON data gracefully.
The beauty of pluck comes from the fact that it’s higher order. Say we have an array that looks like this:
const teletubbies = [
{ color: blue },
{ color: red },
{ color: green }
]
If we want the color from every object in the array, we could do a map accessing each color with dot notation like this:
const colors = teletubbies.map((teletubby) => {
return teletubby.color;
});
The above syntax returns to us an array of colors, one for each element, but it is cumbersome. And if we want to get a different property from each teletubby (I apologize for the weird example), we’ll have to write another similar map that destructures each Teletubby specifically. More complications arise if you want data at a different depth since you’ll need to concern yourself with defaulting and destructuring properly. Here’s how we can do the same thing with pluck
:
const colors = teletubbies.map(pluck('color'));
It gives us a simple API that says something like “for every x, I want its y property”. It scales wonderfully and is a more generic tool for destructuring, rather than a specific destructuring application for one problem.
Here’s my implementation of the pluck
function used throughout this app:
const pluck = (...keys) => (data) => {
return keys.reduce((subData, key) => {
return subData === undefined ? subData : subData[key];
}, data);
};
The rest operator for ...keys
allows us to retrieve properties at arbitrary depth within an object. It also means that if we get undefined
at any point in the chain, we bubble that undefined
value back out to the result without throwing an error. So for example, we can say something like pluck('nest', 'egg', 'bird', 'feather', 'flea' ),
which will return us a function that gets items from objects like this:
{
nest: {
egg: {
bird: {
feather: {
flea: { ... }
}
}
}
}
}
And will simply return undefined
if we give it something like this:
{
nest: {
foo: 100
}
}
With that example in mind, I’ll provide a link to my demo version of the project so that you can see how I’m using pluck
in combination with various array methods to categorize and split up the ratings data for this project.
In the next installment, I’ll talk about using these functions to build our visualizations by feeding them into KendoReact components and beginning the data visualization process.
Resources
The entire source code for this project is available at my GitHub account.
Full Series:
- Part 1: How To Set Up A React NodeJS App With KendoReact For Data Visualization
- Part 2: How To Manage Multiple Data Visualizations In A React App Using KendoReact And React Hooks
- Part 3: How To Work With Complex JSON Data For Visualization With JavaScript
- Part 4: How to Use KendoReact to Create Bar Charts and Tables from the Same Data
- Part 5: How to Export Tabular Data from a React App with KendoReact ExcelExport – Digital Primates
The post How to Work with Complex JSON Data for Visualization with JavaScript appeared first on Digital Primates.