{"id":46694,"date":"2022-03-25T00:00:00","date_gmt":"2022-03-25T07:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/"},"modified":"2026-03-30T14:40:44","modified_gmt":"2026-03-30T21:40:44","slug":"visualize-data-with-griddb-and-the-webapi-using-react-js","status":"publish","type":"post","link":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/","title":{"rendered":"Visualize Data with GridDB and the WebAPI using React.js"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>For this blog, we wanted to showcase using GridDB as a web app&#8217;s best friend. We decided to keep all functionality from this app on the web itself &#8212; this means we will be utilizing the <a href=\"https:\/\/griddb.net\/en\/blog\/griddb-webapi\/\">GridDB WebAPI<\/a> for all steps of the process: schema creation, ingestion, and querying.<\/p>\n<p>The entire process will be handled by our React.js frontend. This means the user will enter their GridDB WebAPI credentials, upload a CSV file of their choosing, select if that container will be <code>COLLECTION<\/code> or <code>TIMESERIES<\/code> and then create the proper schema onto GridDB. Once the container is created, the entirety of the <code>.csv<\/code> file will be uploaded onto the database.<\/p>\n<p>Once the data is in place, you can query to receive the data from your server and then finally visualize it using the <code>recharts<\/code> <a href=\"https:\/\/recharts.github.io\/?p=\/en-US\">library<\/a>.<\/p>\n<h2>Prerequisites<\/h2>\n<p>To follow along, you will need a GridDB server up and running. You will also need to install the GridDB WebAPI and have that running on your server.<\/p>\n<p>For the frontend, you will need to install react.js, along with the charts library. You can see what the <code>package.json<\/code> file looks like here:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">{\n  \"name\": \"griddb-charts\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@emotion\/react\": \"^11.8.2\",\n    \"@emotion\/styled\": \"^11.8.1\",\n    \"@mui\/material\": \"^5.5.0\",\n    \"@testing-library\/jest-dom\": \"^5.16.2\",\n    \"@testing-library\/react\": \"^12.1.4\",\n    \"@testing-library\/user-event\": \"^13.5.0\",\n    \"axios\": \"^0.26.1\",\n    \"react\": \"^17.0.2\",\n    \"react-dom\": \"^17.0.2\",\n    \"react-scripts\": \"5.0.0\",\n    \"recharts\": \"^2.1.9\",\n    \"web-vitals\": \"^2.1.4\"\n  },\n  \"scripts\": {\n    \"start\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test\",\n    \"eject\": \"react-scripts eject\"\n  },\n  \"eslintConfig\": {\n    \"extends\": [\n      \"react-app\",\n      \"react-app\/jest\"\n    ]\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.2%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  }\n}<\/code><\/pre>\n<\/div>\n<p>The top of your file will also take all of your imports:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">import React, { useState, useEffect } from 'react';\nimport '.\/App.css';\nimport { usePapaParse } from 'react-papaparse';\n\nimport {\n  BarChart,\n  Bar,\n  XAxis,\n  YAxis,\n  Tooltip,\n  Legend\n} from \"recharts\";\nimport Box from '@mui\/material\/Box';\nimport InputLabel from '@mui\/material\/InputLabel';\nimport MenuItem from '@mui\/material\/MenuItem';\nimport FormControl from '@mui\/material\/FormControl';\nimport Select from '@mui\/material\/Select';\nimport Container from '@mui\/material\/Container';\nimport TextField from '@mui\/material\/TextField';\nimport Button from '@mui\/material\/Button';\nimport Dialog from '@mui\/material\/Dialog';\nimport DialogActions from '@mui\/material\/DialogActions';\nimport DialogContent from '@mui\/material\/DialogContent';\nimport FormHelperText from \"@mui\/material\/FormHelperText\";\nimport Grid from '@mui\/material\/Grid'<\/code><\/pre>\n<\/div>\n<h2>ETL<\/h2>\n<p>For implementation, we will walk through in the following order: user credentials, creating and send schema\/container, pushing data into the container, querying the data, and then we will finish with showing the data into a chart.<\/p>\n<h3>Credentials<\/h3>\n<p>To begin, we will create some simple text fields to allow the user to enter their user and admin credentials. For our blog, we will simply use the GridDB default values of admin\/admin as a proof of concept.<\/p>\n<p>Also, to keep things simple, we will be using the <a href=\"https:\/\/mui.com\/getting-started\/installation\/\">material ui<\/a> React.js framework.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-html\">        &lt;TextField\n            id=\"user\"\n            label=\"Username\"\n            variant=\"standard\"\n            onChange={handleUser}\n            required={true}\n          \/&gt;\n          &lt;TextField\n            id=\"standard-basic\"\n            label=\"Password\"\n            variant=\"standard\"\n            onChange={handlePass}\n            required={true}\n          \/&gt;<\/code><\/pre>\n<\/div>\n<p>Here you can see that we are handling our textfields with separate functions. We will use React&#8217;s <code>useState<\/code> to handle the changes and save the user&#8217;s input. To keep it simple, we will not have any sort of checking &#8212; we will simply save every input into the state<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">  const [user, setUser] = useState('')\n  const [pass, setPass] = useState('')\n\n  const handleUser = (event) => {\n    let val = event.target.value\n    setUser(val)\n  }\n\n  const handlePass = (event) => {\n    let val = event.target.value\n    setPass(val)\n  }<\/code><\/pre>\n<\/div>\n<p>To make the proper javascript <code>fetch<\/code> requests, we will also need to transform the user&#8217;s credentials into base64. We can do so like so:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">  const [encodedUserPass, setEncodedUserPass] = useState('')\n\n  useEffect(() => {\n    let encodedUserPass = btoa(user + \":\" + pass)\n    setEncodedUserPass(encodedUserPass)\n  }, [pass])<\/code><\/pre>\n<\/div>\n<p>The <code>[pass]<\/code> after the function callback for the <code>useEffect<\/code> just means we will update this specific function when the <code>pass<\/code> state variable is updated. Not the most elegant solution, but it works for our purposes.<\/p>\n<h3>Uploading a CSV File<\/h3>\n<p>First, let&#8217;s allow our user to upload a <code>.csv<\/code> file. This is very easily accomplished using HTML.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-html\">&lt;label &gt;Choose a CSV File to Upload:&lt;\/label&gt;\n\n        &lt;input type=\"file\"\n          id=\"csvFile\" name=\"file\" onChange={fileHandler}\n          accept=\".csv\"&gt;&lt;\/input&gt;\n          <\/code><\/pre>\n<\/div>\n<p>Our <code>fileHandler<\/code> function will utilize the <code>papa-parse<\/code> library to read in the file and parse the contents and set some React states for use later.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">import { usePapaParse } from 'react-papaparse';\n  const { readString } = usePapaParse();\n\n  const [fullCsvData, setFullCsvData] = useState(null);\n  const [fileName, setFileName] = useState('');\n  const [selectedFile, setSelectedFile] = useState(null);\n\n  const fileHandler = (event) => {\n    const file = event.target.files[0]\n    let name = file.name\n    let x = name.substring(0, name.indexOf('.')); \/\/remove the .csv file extension\n    const reader = new FileReader();\n    reader.addEventListener('load', (event) => {\n      var data = event.target.result\n\n      readString(data, {\n        worker: true,\n        complete: (results) => {\n          setFileName(x)\n          console.log(\"selected file: \", results.data[0])\n          setFullCsvData(results.data)\n          setSelectedFile(results.data[0]);\n          setOpen(true)\n        },\n      });\n    });\n\n    reader.readAsText(file);\n\n  };<\/code><\/pre>\n<\/div>\n<p>So, once the user uploads a <code>.csv<\/code> file, the <code>fileHandler<\/code> function will fire off, taking in the file as the <code>event<\/code>. It will then read the file&#8217;s contents and then parse everything. Once parsed, we will set various React states: the file name, the entirety of the csv contents, and the first array of data which corresponds to the column names.<\/p>\n<h3>Setting the Column Types<\/h3>\n<p>When parsing the user&#8217;s file, it can be difficult to reliably parse out the row&#8217;s datatype. To get around this issue, we will simply open up a modal once the file is uploaded and allow the user to set each column&#8217;s datatype. We will use this data to form our object which is used to create the schema with the Web API.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/03\/column_types.png\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/03\/column_types.png\" alt=\"\" width=\"1600\" height=\"799\" class=\"aligncenter size-full wp-image-28101\" srcset=\"\/wp-content\/uploads\/2022\/03\/column_types.png 1600w, \/wp-content\/uploads\/2022\/03\/column_types-300x150.png 300w, \/wp-content\/uploads\/2022\/03\/column_types-1024x511.png 1024w, \/wp-content\/uploads\/2022\/03\/column_types-768x384.png 768w, \/wp-content\/uploads\/2022\/03\/column_types-1536x767.png 1536w, \/wp-content\/uploads\/2022\/03\/column_types-600x300.png 600w, \/wp-content\/uploads\/2022\/03\/column_types-1280x640.png 1280w\" sizes=\"(max-width: 1600px) 100vw, 1600px\" \/><\/a><\/p>\n<p>This is the structure that the WebAPI expects:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">'{\n    \"columns\": [\n        {\n            \"name\": \"timestamp\",\n            \"type\": \"TIMESTAMP\"\n        },\n        {\n            \"name\": \"name\",\n            \"type\": \"STRING\"\n        },\n        {\n            \"name\": \"value\",\n            \"type\": \"FLOAT\"\n        }\n    ],\n    \"container_name\": \"test\",\n    \"container_type\": \"TIME_SERIES\",\n    \"rowkey\": true\n}'<\/code><\/pre>\n<\/div>\n<p>Once the user enters the column information and clicks the Create Schema button, we will prepare the proper data to send via an HTTP request.<\/p>\n<div class=\"clipboard\">\n<pre><code>&lt;Button onClick={handleSchema} variant=\"contained\"&gt;Create Schema&lt;\/Button&gt;<\/code><\/pre>\n<\/div>\n<p>The <code>handleSchema<\/code> function simply calls our <code>putSchema<\/code> function<\/p>\n<h3>GridDB WebAPI HTTP Request (Put Schema\/Container)<\/h3>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">  const handleSchema = () => {\n    if (Object.keys(chartColumns).length !== 0) { \/\/chartColumns is an array of the column names from the csv\n      putSchema(chartColumns)\n    }\n  }\n\n  const putSchema = (obj) => {\n\n    let data = new Object();\n    data.columns = [];\n    let n = Object.keys(obj).length\n    let i = 0\n    for (const property in obj) {\n      if (i &lt; n) {\n        data.columns[i] = { \"name\": property, \"type\": (obj[property]).toUpperCase() }\n        i++\n      }\n    }\n    data[\"container_name\"] = fileName \/\/ grabbed from the react State \n    data[\"container_type\"] = \"COLLECTION\" \/\/ hardcoded for now\n    data[\"rowkey\"] = \"true\"\n\n    let raw = JSON.stringify(data);\n\n    let myHeaders = new Headers();\n    myHeaders.append(\"Content-type\", \"application\/json\")\n    myHeaders.append(\"Authorization\", \"Basic \" + encodedUserPass);\n\n    let requestOptions = {\n      method: 'POST',\n      headers: myHeaders,\n      body: raw,\n      redirect: 'follow'\n    };\n\n    fetch(`http:\/\/${ADDRESS}\/griddb\/v2\/defaultCluster\/dbs\/public\/containers`, requestOptions)\n      .then(response => response.text())\n      .then(result => {\n        setChartColumns(\"Successful. Now Push Data\") \/\/ displays where the object was being formed\n        console.log(result)\n      })\n      .catch(error => {\n        setChartColumns(error)\n        console.log(\"Error: \", error)\n      });\n  }<\/code><\/pre>\n<\/div>\n<p>Here we are making our first Web API HTTP Request. Before we do that, we take all of data we have gathered and form the data structure the API expects. For now, we have hardcoded a <code>COLLECTION<\/code> container type, but this can be easily be fixed by adding a switch onto the modal.<\/p>\n<p>The main thing we need to accomplish is to create an object which has a columns array inside with each column name and type inside. Once the data structure is set, you simply <code>JSON.stringify<\/code> it and send it in the body of the request, along with the <code>requestOptions<\/code>. The last thing to note is that once the request is made, if there is an error, it will be shown in the modal. If successful, a simple message will appear, prompting the user to now push the data.<\/p>\n<h3>GridDB WebAPI Pushing CSV Data to Container<\/h3>\n<p>Next, once the GridDB server has accepted our HTTP request to create the container and its schema, we can now send over the full <code>.csv<\/code> data to our server via an HTTP request.<\/p>\n<p>The user will be required to press the <code>PUSH DATA<\/code> button which will fire off the <code>putData<\/code> function.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">  const handlePushingData = () => {\n    if (fullCsvData !== null) {\n      putData(fullCsvData)\n    }\n  }\n\nconst putData = (data) => {\n\n    data.shift();\n    let removeEmpties = data.filter(ele => ele.length > 1)\n    console.log(\"data: \", removeEmpties)\n\n    let raw = JSON.stringify(removeEmpties)\n    console.log(raw)\n\n    let myHeaders = new Headers();\n    myHeaders.append(\"Content-type\", \"application\/json\")\n    myHeaders.append(\"Authorization\", \"Basic \" + encodedUserPass);\n\n    let requestOptions = {\n      method: 'PUT',\n      headers: myHeaders,\n      body: raw,\n      redirect: 'follow'\n    };\n\n    fetch(`http:\/\/${ADDRESS}\/griddb\/v2\/defaultCluster\/dbs\/public\/containers\/${fileName}\/rows`, requestOptions)\n      .then(response => response.text())\n      .then(result => setChartColumns(\"Successful: \", result))\n      .catch(error => {\n        setChartColumns(error)\n        console.log(\"Error: \", error)\n      });\n  }<\/code><\/pre>\n<\/div>\n<p>Similar to the <code>putSchema<\/code> function, we grab the entire contents of our data from our React&#8217;s state and then do some basic massaging to get the proper data to send. First, we get rid of the first element of the array as this one is simply the column names. We then get rid of any empty elements (if any). Everything else should be self-explanatory &#8212; the only caveat being that the HTTP Request method for this one is a <code>PUT<\/code> (vs. a <code>POST<\/code>).<\/p>\n<p>If successful, the amount of columns will be displayed in the modal. If an error, it will also be displayed in the modal. So far, we&#8217;ve ingested our <code>.csv<\/code> data into our server. Next up is querying and displaying.<\/p>\n<h3>Querying<\/h3>\n<p>For demo purposes, we will also query the GridDB server to re-retrieve our data to visualize it. Querying with the WebAPI is very easy:<\/p>\n<div class=\"clipboard\">\n<pre><code>curl -X POST --basic -u admin:admin -H \"Content-type:application\/json\" http:\/\/127.0.0.1:8080\/griddb\/v2\/defaultCluster\/dbs\/public\/containers\/test\/rows -d  '{\"limit\":1000}'  <\/code><\/pre>\n<\/div>\n<p>For this application, we will have it load after the user enters their credentials and hits the QUERY button which fires off the <code>handleSubmitCreds<\/code> function. The server will respond with the full data of your query; we will then grab that data and transform it into something that <code>recharts<\/code> can display.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">  const handleSubmitCreds = () => {\n    let raw = JSON.stringify({\n      \"limit\": 100\n    });\n\n    let myHeaders = new Headers();\n    myHeaders.append(\"Content-type\", \"application\/json\")\n    myHeaders.append(\"Authorization\", \"Basic \" + encodedUserPass);\n\n    let requestOptions = {\n      method: 'POST',\n      headers: myHeaders,\n      body: raw,\n      redirect: 'follow'\n    };\n\n    fetch(`http:\/\/${ADDRESS}\/griddb\/v2\/defaultCluster\/dbs\/public\/containers\/CEREAL\/rows`, requestOptions)\n      .then(response => response.text())\n      .then(result => {\n        let resp = JSON.parse(result)\n        let rows = resp.rows\n\n        let c = resp.columns\n        let columns = [];\n        c.forEach(val => columns.push(val.name))\n\n        let map = new Map();\n        let fullChartData = [];\n        \/\/ transform data into more usable obj\n        for (let i = 0; i &lt; 72; i++) { \/\/hard coding the length of rows (72)\n          for (let j = 0; j &lt; 16; j++) { \/\/ hard coding length of columns (16)\n            map.set(columns[j], rows[i][j])\n          }\n          const obj = Object.fromEntries(map);\n          fullChartData.push(obj)\n        }\n        setData(fullChartData)\n\n      })\n      .catch(error => console.log('error', error));\n  }<\/code><\/pre>\n<\/div>\n<p>The empty array in the <code>useEffect<\/code> just tells our React to only run this function on page load, not on every re-render.<\/p>\n<h2>Visualizing Data<\/h2>\n<p>The above function not only queried the data, but it also managed to transform the data into a more usable form.<\/p>\n<p>To get the data that <code>recharts<\/code> expects, we will use the Javascript <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Map\">map object<\/a> to set key:value data pairs and then create an object out of that map using the <code>Object.fromEntries<\/code>.<\/p>\n<p>For this demo, we will be using the <a href=\"https:\/\/www.kaggle.com\/crawford\/80-cereals\">kaggle cereals dataset<\/a>. With the data loaded in from the function above, we can place all the data onto a line chart, but I think a more interesting usecase would be showing one individual cereal&#8217;s macro and micro nutrients onto a bar chart. To do so, we will create a dropdown list with every single cereal listed. When a user picks a cereal, the app will find the corresponding data and display it on the chart<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-html\">    &lt;FormControl fullWidth&gt;\n      &lt;InputLabel id=\"demo-simple-select-label\"&gt;Cereal&lt;\/InputLabel&gt;\n      &lt;Select labelId=\"demo-simple-select-label\" id=\"demo-simple-select\" value={choice} label=\"Cereal\" onChange={handleChange}&gt;\n        &lt;MenuItem value={\"100% Bran\"}&gt;100% Bran&lt;\/MenuItem&gt;\n        &lt;MenuItem value={\"100% Natural Bran\"}&gt;100% Natural Bran&lt;\/MenuItem&gt;\n        &lt;MenuItem value={\"All-Bran\"}&gt;All Bran&lt;\/MenuItem&gt;\n        &lt;MenuItem value={\"All-Bran with Extra Fiber\"}&gt; All-Bran with Extra Fiber&lt;\/MenuItem&gt;\n        &lt;MenuItem value={\"Almond Delight\"}&gt;Almond Delight&lt;\/MenuItem&gt;<\/code><\/pre>\n<\/div>\n<p>When the user selects a cereal, our <code>handleChange<\/code> function will fire off:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">  const handleChange = (event) => {\n    let val = event.target.value\n    console.log(\"val: \", val)\n    setChoice(val);\n  };<\/code><\/pre>\n<\/div>\n<p>Which will set the React state for choice with the cereal name. When the app detects that change, it will fire off the following function:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">  useEffect(() => {\n    if (data !== null) {\n      let userChoice = data.find(val => val.NAME == choice)\n      setDisplayedData(userChoice);\n    } else console.log(\"data still null\")\n  }, [choice])<\/code><\/pre>\n<\/div>\n<p>This function will use the javascript array find method which locate the proper data from the full dataset which is saved in our React state as <code>data<\/code>. Once it finds this data, the bar chart will display the proper data (<code>displayedData<\/code>):<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-html\">&lt;BarChart\n          width={1500}\n          height={500}\n          data={[displayedData]}\n          margin={{\n            top: 5,\n            right: 30,\n            left: 20,\n            bottom: 5,\n          }}\n        &gt;\n          &lt;XAxis dataKey=\"NAME\" \/&gt;\n          &lt;YAxis \/&gt;\n          &lt;Tooltip \/&gt;\n          &lt;Legend \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"a\" dataKey=\"MANUFACTURER\" fill=\"#FFF\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"a\" dataKey=\"TYPE\" fill=\"#FFF\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"b\" dataKey=\"CALORIES\" fill=\"red\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"c\" dataKey=\"PROTEIN\" fill=\"pink\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"c\" dataKey=\"FAT\" fill=\"orange\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"d\" dataKey=\"SODIUM\" fill=\"#82ca9d\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"d\" dataKey=\"FIBER\" fill=\"#82ca9d\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"c\" dataKey=\"CARBO\" fill=\"purple\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"e\" dataKey=\"SUGARS\" fill=\"#82ca9d\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"e\" dataKey=\"POTASS\" fill=\"#82ca9d\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"f\" dataKey=\"VITAMINS\" fill=\"#82ca9d\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"f\" dataKey=\"SHELF\" fill=\"#82ca9d\" \/&gt;\n          &lt;Bar type=\"monotone\" stackId=\"f\" dataKey=\"WEIGHT\" fill=\"#82ca9d\" \/&gt;\n        &lt;\/BarChart&gt;        <\/code><\/pre>\n<\/div>\n<p>For this chart, you can stack up the different micro\/macro nutrients however you like with different colors. For this demo, I did not set anything other than setting calories on its own bar so that we can see those. Here is the chart for Cinnamon Toast Crunch<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/03\/basic_bar_chart.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2022\/03\/basic_bar_chart.png\" alt=\"\" width=\"1531\" height=\"659\" class=\"aligncenter size-full wp-image-28099\" srcset=\"\/wp-content\/uploads\/2022\/03\/basic_bar_chart.png 1531w, \/wp-content\/uploads\/2022\/03\/basic_bar_chart-300x129.png 300w, \/wp-content\/uploads\/2022\/03\/basic_bar_chart-1024x441.png 1024w, \/wp-content\/uploads\/2022\/03\/basic_bar_chart-768x331.png 768w, \/wp-content\/uploads\/2022\/03\/basic_bar_chart-600x258.png 600w\" sizes=\"(max-width: 1531px) 100vw, 1531px\" \/><\/a><\/p>\n<h2>Conclusion<\/h2>\n<p>Now we can easily ingest and load up our csv data into beautiful react.js <code>recharts<\/code>.<\/p>\n<p>Full source code can be found in our <a href=\"\">Github<\/a> page.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction For this blog, we wanted to showcase using GridDB as a web app&#8217;s best friend. We decided to keep all functionality from this app on the web itself &#8212; this means we will be utilizing the GridDB WebAPI for all steps of the process: schema creation, ingestion, and querying. The entire process will be [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":28154,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-46694","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Visualize Data with GridDB and the WebAPI using React.js | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"Introduction For this blog, we wanted to showcase using GridDB as a web app&#039;s best friend. We decided to keep all functionality from this app on the web\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Visualize Data with GridDB and the WebAPI using React.js | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"Introduction For this blog, we wanted to showcase using GridDB as a web app&#039;s best friend. We decided to keep all functionality from this app on the web\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/\" \/>\n<meta property=\"og:site_name\" content=\"GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/griddbcommunity\/\" \/>\n<meta property=\"article:published_time\" content=\"2022-03-25T07:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-30T21:40:44+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.griddb.net\/wp-content\/uploads\/2022\/03\/react.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1160\" \/>\n\t<meta property=\"og:image:height\" content=\"653\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Israel\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:site\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Israel\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/\"},\"author\":{\"name\":\"Israel\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740\"},\"headline\":\"Visualize Data with GridDB and the WebAPI using React.js\",\"datePublished\":\"2022-03-25T07:00:00+00:00\",\"dateModified\":\"2026-03-30T21:40:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/\"},\"wordCount\":1319,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2022\/03\/react.png\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/\",\"url\":\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/\",\"name\":\"Visualize Data with GridDB and the WebAPI using React.js | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2022\/03\/react.png\",\"datePublished\":\"2022-03-25T07:00:00+00:00\",\"dateModified\":\"2026-03-30T21:40:44+00:00\",\"description\":\"Introduction For this blog, we wanted to showcase using GridDB as a web app's best friend. We decided to keep all functionality from this app on the web\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2022\/03\/react.png\",\"contentUrl\":\"\/wp-content\/uploads\/2022\/03\/react.png\",\"width\":1160,\"height\":653},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/griddb.net\/en\/#website\",\"url\":\"https:\/\/griddb.net\/en\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL\",\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/griddb.net\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/griddb.net\/en\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/griddb.net\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/griddbcommunity\/\",\"https:\/\/x.com\/GridDBCommunity\",\"https:\/\/www.linkedin.com\/company\/griddb-by-toshiba\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740\",\"name\":\"Israel\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g\",\"caption\":\"Israel\"},\"url\":\"https:\/\/www.griddb.net\/en\/author\/israel\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Visualize Data with GridDB and the WebAPI using React.js | GridDB: Open Source Time Series Database for IoT","description":"Introduction For this blog, we wanted to showcase using GridDB as a web app's best friend. We decided to keep all functionality from this app on the web","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/","og_locale":"en_US","og_type":"article","og_title":"Visualize Data with GridDB and the WebAPI using React.js | GridDB: Open Source Time Series Database for IoT","og_description":"Introduction For this blog, we wanted to showcase using GridDB as a web app's best friend. We decided to keep all functionality from this app on the web","og_url":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2022-03-25T07:00:00+00:00","article_modified_time":"2026-03-30T21:40:44+00:00","og_image":[{"width":1160,"height":653,"url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2022\/03\/react.png","type":"image\/png"}],"author":"Israel","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"Israel","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#article","isPartOf":{"@id":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/"},"author":{"name":"Israel","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740"},"headline":"Visualize Data with GridDB and the WebAPI using React.js","datePublished":"2022-03-25T07:00:00+00:00","dateModified":"2026-03-30T21:40:44+00:00","mainEntityOfPage":{"@id":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/"},"wordCount":1319,"commentCount":0,"publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"image":{"@id":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2022\/03\/react.png","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/","url":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/","name":"Visualize Data with GridDB and the WebAPI using React.js | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#primaryimage"},"image":{"@id":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2022\/03\/react.png","datePublished":"2022-03-25T07:00:00+00:00","dateModified":"2026-03-30T21:40:44+00:00","description":"Introduction For this blog, we wanted to showcase using GridDB as a web app's best friend. We decided to keep all functionality from this app on the web","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.griddb.net\/en\/blog\/visualize-data-with-griddb-and-the-webapi-using-react-js\/#primaryimage","url":"\/wp-content\/uploads\/2022\/03\/react.png","contentUrl":"\/wp-content\/uploads\/2022\/03\/react.png","width":1160,"height":653},{"@type":"WebSite","@id":"https:\/\/griddb.net\/en\/#website","url":"https:\/\/griddb.net\/en\/","name":"GridDB: Open Source Time Series Database for IoT","description":"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL","publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/griddb.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/griddb.net\/en\/#organization","name":"Fixstars","url":"https:\/\/griddb.net\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/","url":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/griddbcommunity\/","https:\/\/x.com\/GridDBCommunity","https:\/\/www.linkedin.com\/company\/griddb-by-toshiba"]},{"@type":"Person","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740","name":"Israel","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g","caption":"Israel"},"url":"https:\/\/www.griddb.net\/en\/author\/israel\/"}]}},"_links":{"self":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46694","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/comments?post=46694"}],"version-history":[{"count":2,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46694\/revisions"}],"predecessor-version":[{"id":55157,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46694\/revisions\/55157"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media\/28154"}],"wp:attachment":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media?parent=46694"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/categories?post=46694"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/tags?post=46694"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}