In this article, we’re going to add scaffolding for our React and Progress KendoReact application. We’ll use KendoReact’s view layout functionality to house multiple different views. Let’s pick up from where we left the application last time. Our last installment left us with this rather plain-looking series of static bar charts:
Today we’re going to use KendoReact Layout to allow a user to flip between multiple data visualization views. React is perfect for this kind of conditional rendering, and KendoReact’s layout components will enable us to manage numerous different types of data visualizations within one application.
What We’ll Be Building
Our final product today will look something like this:
So without further ado, let’s get started!
Static Site Elements
Let’s build out a header that remains the same between different views. The first thing we’ll do is strip out the placeholder charts that I’m displaying in App.js
:
import React from 'react';
import "hammerjs";
import './App.css';
const App = () => {
return (<></>);
}
export default App;
I’ve also converted the App functional component to use an arrow function. It makes no real difference for our purposes, but I find it a bit neater for presentation.
The next thing we’ll do is throw a header at the top of our single-page application:
const App = () => {
return (
<>
<h1>
<span role="img" aria-label="">🍕</span>
Pizza-o-matic
<span role="img" aria-label="">🍕</span>
</h1>
</>
);
};
App.css
file so far for reference:h1 {
background: url('/header.svg') no-repeat;
color: white;
margin: 0;
font-weight: bold;
line-height: 1;
font-size: 2.5rem;
padding: 2rem;
text-align: center;
}
h1 span {
display: inline-block;
padding: 0 0.5rem;
}
@media (max-width: 700px) {
h1 {
padding: 1rem;
font-size: 2rem;
}
}
@media (max-width: 500px) {
h1 {
font-size: 1.5rem;
}
}
We should now see just a header spanning the entire browser window. This header will be constant, while different data visualization views beneath are allowed to change.
React Hooks for Managing View State
Now we can begin to control the conditional flow that will allow our application to render different views. There are two pieces of state that we want to keep track of while using this application:
- What style of chart a user is viewing (chart or table)
- What region of the store’s ratings the user is viewing
We’ll add these two pieces of state by using the React State Hook. Let’s first add a way to represent the chart or table view:
const [ isChartView, setChartView ] = useState(true);
useState
function returns an array with a value and a function to change that value. So now we have a boolean representing either chart view or table view. The next step is similar but will use an integer to represent which region tab we want to view on the page.const SELECTED_KEY = "selected";
const App = () => {
const [ selected, setSelected ] = useState(
parseInt(localStorage.getItem(SELECTED_KEY), 10) || 0
);
const onTabSelect = ({ selected } = {}) => {
setSelected(selected);
localStorage.setItem(SELECTED_KEY, selected);
};
const [ isChartView, setChartView ] = useState(true);
...
isChartView
.
Here is some sample code you can include in App.js
so you can get a feel for how our application edits these within our app:import React, { useState } from 'react';
import "hammerjs";
import './App.css';
const SELECTED_KEY = "selected";
const App = () => {
const [ isChartView, setChartView ] = useState(true);
const [ selected, setSelected ] = useState(
parseInt(localStorage.getItem(SELECTED_KEY), 10) || 0
);
const onTabSelect = ({ selected } = {}) => {
setSelected(selected);
localStorage.setItem(SELECTED_KEY, selected);
};
return (
<>
<h1>
<span role="img" aria-label="">
🍕
</span>
Pizza-o-matic
<span role="img" aria-label="">
🍕
</span>
</h1>
<div>
<button onClick={() => onTabSelect({ selected: 1 })}>
Select Tab 1
</button>
<button onClick={() => onTabSelect({ selected: 2 })}>
Select Tab 2
</button>
{`Tab selected: ${selected}`}
</div>
<div>
<button onClick={() => setChartView(!isChartView)}>
Toggle Chart View
</button>
{`${isChartView ? 'Chart View' : 'Table View'}`}
</div>
</>
);
};
export default App;
This snippet showcases some of the fundamentals of conditional rendering that make React so useful for representing state within an application. At this point, the application should look something like this:
Plugging React State into KendoReact Layout Components
KendoReact’s layout functionality works beautifully with React Hooks. It allows us to change the way we visualize data based on the current state of the application. We’ll be using the TabStrip
component which will hold multiple TabStripTab
children.
import { TabStrip, TabStripTab } from '@progress/kendo-react-layout';
We can then replace our example code and add this tab layout functionality to our app like so:
<TabStrip
selected={selected}
onSelect={onTabSelect}
tabPosition="left"
animation={false}
>
<TabStripTab title={'Tab 1'}>
Tab 1 Chart
</TabStripTab>
<TabStripTab title={'Tab 2'}>
Tab 2 Chart
</TabStripTab>
</TabStrip>
Now let’s add in a way to switch between Chart View and Table View. We’ll add in two basic buttons to switch between the two views. App.js should now look something like this:
const App = () => {
const [ isChartView, setChartView ] = useState(true);
const [ selected, setSelected ] = useState(
parseInt(localStorage.getItem(SELECTED_KEY), 10) || 0
);
const onTabSelect = ({ selected } = {}) => {
setSelected(selected);
localStorage.setItem(SELECTED_KEY, selected);
};
return (
<>
<h1>
<span role="img" aria-label="">
🍕
</span>
Pizza-o-matic
<span role="img" aria-label="">
🍕
</span>
</h1>
<button onClick={() => setChartView(true)}>Chart View</button>
<button onClick={() => setChartView(false)}>Table View</button>
<TabStrip
selected={selected}
onSelect={onTabSelect}
tabPosition="left"
animation={false}
>
<TabStripTab title={'Tab 1'}>
{`Tab 1 ${isChartView ? 'Chart' : 'Table'} View`}
</TabStripTab>
<TabStripTab title={'Tab 2'}>
{`Tab 2 ${isChartView ? 'Chart' : 'Table'} View`}
</TabStripTab>
</TabStrip>
</>
);
};
With the view looking like this:
Now the final step will be to pretty up the data panel area a little bit:
<TabStrip
selected={selected}
onSelect={onTabSelect}
tabPosition="left"
animation={false}
>
<TabStripTab title={"Tab 1"}>
<div className="ratings-header">
<h2>Company Ratings</h2>
<span className="buttons-span">
<img
src="chart-bar.svg"
alt="chart view"
className={isChartView ? "active" : "inactive"}
onClick={() => setChartView(true)}
/>
<img
src="table.svg"
alt="cell view"
className={isChartView ? "inactive" : "active"}
onClick={() => setChartView(false)}
/>
</span>
</div>
<div>{`Tab 1 ${isChartView ? "Chart" : "Table"} View`}</div>
</TabStripTab>
<TabStripTab title={"Tab 2"}>
<div className="ratings-header">
<h2>Company Ratings</h2>
<span className="buttons-span">
<img
src="chart-bar.svg"
alt="chart view"
className={isChartView ? "active" : "inactive"}
onClick={() => setChartView(true)}
/>
<img
src="table.svg"
alt="cell view"
className={isChartView ? "inactive" : "active"}
onClick={() => setChartView(false)}
/>
</span>
</div>
<div>{`Tab 2 ${isChartView ? "Chart" : "Table"} View`}</div>
</TabStripTab>
</TabStrip>
With some final touches to the App.css file, we’re all finished with this portion of the guide:
.ratings-header {
text-align: center;
}
.ratings-header .buttons-span {
margin-right: 40px;
float: right;
}
.ratings-header h2 {
display: inline;
font-size: 30px;
}
.ratings-header img {
height: 30px;
width: 35px;
margin: 5px;
padding: 5px 5px;
cursor: pointer;
}
.ratings-header .active {
background: #0040FF40;
border-radius: 10px;
height: 35px;
width: 40px;
}
.flex-container {
list-style: none;
display: inline;
flex-wrap: nowrap;
}
.flex-item {
border: 1px solid black;
border-radius: 10px;
color: black;
margin: 10px;
padding: 10px;
display: inline-block;
font-size: 15px;
}
And that’s all there is to it!
What’s next?
In the next installment, we’ll go over how to wrangle JSON data into a format that lends itself to multiple views like this. That way, we’ll see our application respond to any data that we feed it. Feel free to add comments below if you have questions or ideas about this topic.
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