Building a Recharts Dashboard with Cube
Tags: javascript, webdev, react, tutorial
Published: 2022-03-31 13:42:21

This guest post was written by Julien Bras. He's an Innovation Team Leader at @Wiiisdom. You can get in touch with him through his [website](https://github.com/julbrs) or [Twitter](https://twitter.com/_julbrs).

---

Great job, developer. You’ve nearly finished your first major React-based project for that new customer. 

But now you’re asked to add a dashboard to show sales revenues or user retention percentage. You know it will take you weeks with traditional methods—computing the data to share, building an endpoint to expose the right data, handling it on the front-end side, presenting it correctly, tweaking the metrics. Isn’t there a more straightforward way? 

Yes, there is.

This tutorial will show you how to build a dashboard using [Recharts](https://recharts.org/), a React library that offers you a set of chart components to speed up the creation of a dashboard, and [Cube](https://cube.dev/), a Headless BI tool that allows you to expose your application database via a set of APIs. The combination will allow you to play with your data and simply copy/paste the generated dashboard code content to your React application. 

Here is the expected result of this tutorial:

![Recharts Dashboard built with Cube](https://i.imgur.com/s7cGBsH.png)

## Introducing Cube

[Cube](https://cube.dev/) positions itself as “Headless BI for building
data applications.” The tool acts as a bridge between the data that is stored, generally in a database (PostgreSQL, MySQL, etc.), and your front-end application that is consuming an API.

![Cube architecture](https://imgur.com/FluGFqo.png)

Cube is available in two flavors: an open-source product, generally named Cube.js, which you must [host yourself](https://cube.dev/docs/getting-started/docker); and Cube Cloud, an enterprise-ready service with [high availability and scalability](https://cube.dev/docs/cloud). Both options provide the same features.

## Introducing Recharts

[Recharts](https://recharts.org/) is a React library designed to help you create nice charts. By providing an expanded set of [pre-existing charts](https://recharts.org/en-US/api/AreaChart), it allows you to present data in the way you need. 

Let’s take the following piece of code, where `data` is a simple JavaScript array containing the data:

```
<BarChart width={730} height={250} data={data}>
  <CartesianGrid strokeDasharray="3 3" />
  <XAxis dataKey="name" />
  <YAxis />
  <Tooltip />
  <Legend />
  <Bar dataKey="pv" fill="#8884d8" />
  <Bar dataKey="uv" fill="#82ca9d" />
</BarChart>
```

It will be shown like this:

![Recharts example](https://i.imgur.com/gw8mMKX.png)

Recharts is a very common solution since it integrates easily in your React environment via the multiple components available. It’s also very customizable to match your requirements: color, style, chart type, etc. You can also specify how to label content, define axis organization, choose the correct shape, and so forth

But because it’s just a front-end library, it needs a `{data}` object with all the content shown on the chart. It’s obvious, but it can be complex to produce this information, for example, if the application is relying on a traditional back end with a classic database system like PostgreSQL or MySQL.

There are also other options for rendering charts on a web application:

* [Charts.js](https://www.chartjs.org/) is a popular solution, but it’s not a React library so you may need to rely on third-party integrations like [this one](https://github.com/reactchartjs/react-chartjs-2). 
* [D3](https://d3js.org/) is also a classic option, but it’s generally much more complex to integrate D3 into a React application, because both libraries will try to access the document object model (DOM).

In this tutorial, you’ll combine [Cube](https://cube.dev/) and Recharts. The good news is that [Cube](https://cube.dev/) supports out-of-the-box Recharts as a charting engine, saving you a lot of time when it’s time to write code.

## Build a Recharts Dashboard with React and Cube

Let’s build the dashboard!

To reproduce the results here, use a sample database available online. You’ll use the MySQL [Employee Sample Database](https://dev.mysql.com/doc/employee/en/). Based on this data, you will build charts to highlight useful metrics:

- Number of employees per department, gender, birth date, etc.
- Average salary per department, gender, hire date, etc.

### Prerequisites

You need to have `docker` and `docker-compose` to use the open-source version of Cube. Since you will spin-up a local MySQL database containing the sample data, you will use Docker to start both a MySQL container and a Cube container. You also need to have `node` and `npm` installed to create the React application for the dashboard. 

With that in place, we can begin.

### Start Cube

To start, you’ll follow the [docker-compose](https://cube.dev/docs/getting-started/docker/compose) steps.

In an empty new folder named `cube`, create a `docker-compose.yml` file:

```
version: '2.2'

services:
  cube:
    image: cubejs/cube:latest
    ports:
      - 4000:4000
    environment:
      - CUBEJS_DEV_MODE=true
    volumes:
      - .:/cube/conf
  database:
    image: genschsa/mysql-employees
    environment:
      - MYSQL_ROOT_PASSWORD=pass
```

It will allow you to define the two containers needed:
- `cubejs/cube` is obviously the Cube image (started in development mode `CUBEJS_DEV_MODE=true` to use the playground, which you’ll see later)
- `genschsa/mysql-employees` is a MySQL server image with the employee sample database already loaded

Then, run the following to start Cube with the database:

```
docker-compose up
```

Both containers will start up and will be able to communicate with each other.

### Start Cube via Cube Cloud

If you want to use Cube Cloud instead, the process is easier than using Docker. The free-tier is [ generous](https://cube.dev/pricing/) for testing the SaaS solution. 

From [Cube Cloud](https://cubecloud.dev/), log in, for example by using your GitHub account. 

![Starting Cube Cloud](https://i.imgur.com/yuffhcP.png)

Then create a deployment: 

![Create a Deployment](https://i.imgur.com/2HVUXav.png)

You can either import an existing project from GitHub, or create a new project from scratch: 

![Create a project](https://i.imgur.com/uKL7fWl.png)

### Connect to the Database

Let’s roll back to the local deployment. Once the containers are up and running, you’ll be able to connect to `http://localhost:4000` via any browser.

![Cube.js playground](https://i.imgur.com/iK1NPGd.png)

The first task is to connect to the database where your data is located. In your case, you need to connect to the employee sample data. So first select MySQL, then configure the connection:

![Configuration of your MySQL database in Cube](https://imgur.com/z7bVhrv.png)

* Hostname: `database`
* Port: `3306`
* Database: `employees`
* Username: `root`
* Password: `pass` 

(Side note: the `root` password is set in the `docker-compose.yml` file as `pass`. Yes, it’s a local deployment. It should not be shipped to your production environment.)

 An `.env` file is generated after this step to store the database credential information.

### Generate a Schema

The important next step is to generate a schema of your database. It will define the API for later interaction. 

Select the tables as shown in the screenshot below and click on **Generate Schema**.

![Cube Schema Generation](https://i.imgur.com/pcq421H.png)

It will create a set of JavaScript files located in the `schema/` folder, next to your `docker-compose.yml` file. Each file describes how to use each table of your database, that is, which fields can be used as a metric (number of employees), a dimension (department name), or what links can be done between tables. The [dedicated section](https://cube.dev/docs/schema/getting-started) of the documentation is a good starting point to get a good foundation of schema in Cube.

Make sure to replace the generated files with the one you can find in [the GitHub repository for this tutorial](https://github.com/julbrs/cube-recharts-tutorial/tree/main/cube/schema). The files here have been carefully designed to let Cube work well with this particular database.

### Start Playing With Your Data

Once your schema is available, you can start experimenting and build your app. 

For example, go to the **Build** section of the app. Select `Employee Count` as the measure, and `Departments Name` as the dimensions, and keep the **Segment**, **Time** and **Filters** empty. Use a **Bar** chart instead of **Line** and click on **Run** in the middle of the screen. You will see this kind of chart:

![First Chart generated via Cube](https://i.imgur.com/rOK1YmL.png)

Take some time to play with this interface. It’s called the playground, after all, so experiment with your data. You can explore measures and dimensions as well as chart styles. 

You can also define the chart engine for your output. In our case, we want to select first **React** then **Recharts**.

![Switch Chart Engine](https://i.imgur.com/nFvYclM.png)

You can also switch between the following:
* **Chart** renders a test chart.
* **JSON Query** shows the JSON data sent to the Cube API.
* **GraphiQL** shows the equivalent information if you want to use the GraphiQL Cube API.
* **Code** generates the code for the current selected engine. (We will use it shortly.)
* **SQL** shows the exact SQL query sent to the database engine.

The screenshot below is of the code screen: 

![Recharts Code](https://i.imgur.com/SvlINg5.png)

This code can be copy-pasted to any React stack app to include the current element of the playground (in our case, a Recharts chart that is built based on the Cube API). If you scroll down, you’ll see the Cube API information:

```
const cubejsApi = cubejs(
  'APIKEY',
  { apiUrl: 'http://localhost:4000/cubejs-api/v1' }
);
```

Here is the query that is sent to the Cube engine:

```
      query={{
  "measures": [
    "Employees.count"
  ],
  "timeDimensions": [],
  "order": {
    "Employees.count": "desc"
  },
  "filters": [],
  "dimensions": [
    "Departments.Name"
  ]
}}
```

And also the graph component from Recharts:

```
  return (
  <CartesianChart resultSet={resultSet} ChartComponent={BarChart}>
    {resultSet.seriesNames().map((series, i) => (
      <Bar
        key={series.key}
        stackId="a"
        dataKey={series.key}
        name={series.title}
        fill={colors[i]}
      />
    ))}
  </CartesianChart>
```

This code saves you hours during dashboard coding. You simply have to organize the elements on the page correctly and define a set of environment variables (Cube API URL, Cube API Token) to have a production-ready dashboard.

### Build Your Recharts Dashboard

The goal of this section is to integrate the various elements generated from the Cube playground into a React application.

Create a new React application using the [Create React App](https://create-react-app.dev/docs/getting-started/) starter:

```
npx create-react-app react-app
```

Add some needed libraries (_Recharts_ for charting, _CubeJs_ for connecting to Cube API, _AntD_ for styling, _Use Deep Compare_ for a React Hook used by the code produced by Cube):

```
cd react-app
npm add @cubejs-client/core @cubejs-client/react antd use-deep-compare recharts
```

Start your development server:

```
npm start
```

Copy-paste the content of the code screen of your first query in a new file in `src/charts/EmployeesPerDept.js`

Remove the last two lines at the end of the file:

```
const rootElement = document.getElementById('root');
ReactDOM.render(<ChartRenderer />, rootElement);
```

Replace the removed code with a classic component export to declare the chart as a React functional component that can be used in the main `src/App.js` file: 

```
export default ChartRenderer;
```

Now, modify the `src/App.js`:

```
import EmployeesPerDept from "./charts/EmployeesPerDept";

function App() {
  return (
    <div className="App">
      <EmployeesPerDept />
    </div>
  );
}

export default App;
```

If you followed all the steps, you should have the chart below on your development server:

![Recharts chart shown on React application](https://i.imgur.com/vkY3Vfz.png)


You’re welcome to explore [this tutorial’s GitHub repository](https://github.com/julbrs/cube-recharts-tutorial/) containing the schema for the Cube application (under `cube/`) and the final React application (under `react-app/`). It contains the Recharts dashboard with the multiple charts you saw at the start of this tutorial.

## Learn More

If you want to learn more about Cube and Recharts, start by working on [query acceleration](https://cube.dev/docs/caching/pre-aggregations/getting-started/). It allows you to speed up the execution of the query by adding pre-aggregation.

There is also a prebuilt Dashboard App that allows you to build your React app directly based on popular templates:

![Cube Dashboard App](https://i.imgur.com/53JOyrZ.png)

You can use the **Add to Dashboard** button to add any query built via the playground directly. It’s even quicker than the process described in this tutorial.

## What Have You Learned Today?

At first, building a custom dashboard integrated into a React application seems like a complex task. But with the right tools, it can be as simple as deciding what to show as a metric and how to present it. The Cube playground handles all the complexity without limiting you to its default values. You can explore the [Cube API documentation](https://cube.dev/docs/) and the [Recharts API documentation](https://recharts.org/en-US/api) to understand how to customize the generated code.

If your project is dealing with analytics, it’s worth trying Cube. Don’t hesitate to ping the team on their [Slack channel](https://slack.cube.dev/). They’re very responsive and helpful, especially if you’re a new player.