Using React + Google Sheets as your CMS

Ryan McNierney
6 min readSep 29, 2018

--

I’ll start this tutorial by admitting you shouldn’t actually use Google Sheets as your CMS for a production level site or project. However, a few use cases come to mind:

  • For non-technical people to have write access to your “database”
  • Ability to send any Google Sheet data to a react application
  • React practice

By the end of this tutorial, you will be able to serve up any data from a Google Sheet into a real React app. Let’s get started.

For this tutorial, we are going to use create-react-app as our starting point. Why create-react-app? It’s simple to use (no wepback or babel configuration) and it works. First, create a new directory and cd into it.

npx create-react-app sheets-cms-demo
cd sheets-cms-demo
npm start

Your browser should open to localhost:3000 and display the following:

Now, we’ll jump into the code. Let’s take a quick look at the file structure create-react-app sets up automatically:

sheets-cms-demo
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── registerServiceWorker.js
// App.js is where will will be making the majority of our changes.

Open App.js and inspect the main component that creates your browser view. Any saved changes made to App.js will automatically be reflected in your browser. See example of a change below:

Now that the react-app is set up, let’s head over to Google Sheets to build your “database”. For this tutorial, we are going to create a simple webpage that will display the favorite dogs of our employees. We will ask employees to fill out this sheet and have the responses reflected in our react app in real time.

Once we have some data, we can send it back to our react-app. The tool we will use to achieve this is Tabletop.js. Tabletop is a really simple npm package that allows us to take our Google Sheet data and export it as a JSON object. On the react side, we can take that JSON response and use it any way we want. Pretty cool.

Important notes on your Google Sheet setup — Tabletop will export your data as an array. Each row will be created as an object with the column headers as the properties.

  • No empty column headers
  • No empty rows. Tabletop will stop reading data if there are any blank rows

First, let’s install Tabletop into our project.

npm install tabletop

In order for Tabletop to read our data there are a few quick changes we will need to make to our Google Sheet settings.

  1. Open the File menu and click Publish to web
  2. Towards the bottom select Start publishing. *The default setting will export the entire document. You can select a specific tab to export if needed. Tabletop will also by default only grab your first tab if you have multiple. The Tabletop docs have info on grabbing specific tabs.

3. Save your spreadsheet key. From the URL, your spreadsheet key will be the entire string after /spreadsheets/d/KEY/edit#gid=0

Back to react.

We will need to make a few updates to our App.js file before we start working with Tabletop. We will be adding a local state to this component so we can store the results from our Tabletop call and reflect any updates made in Google Sheets. Next, update the App.js file to include the following local state with our data initialized as an empty array. Remember, the response we are getting from Tabletop will be an array.

Now it’s time to grab our data. Let’s import Tabletop into App.js and add the Tabletop init function to a componentDidMount() call. Make sure to update the key with your Google Sheet key we saved before. Right now, we are simply logging the data to the console in the callback function.

Open up your browser and your console. When you refresh you should see your new array logged out to the console.

That’s tabletop at work. There is a lot more functionality in the documentation, but for our project that is all we need.

Now we want to update our local state we setup with the new data we get from Tabletop. In the callback function we will update the simple console.log to set our state with the new Tabletop data.

Now if we open our console and refresh we are going to see the updated state console logged out from line 29. We will see the state log twice — once with the initial empty array and a second time with the data once it’s loaded

Now that we have the our data stored on local state, we can write up some simple JSX to display the favorite dogs of our employees. We’ll use a map function to loop over the array and display each employee.

The favorite dogs should now be displayed in our browser.

Since we are using the map function, any update we make to our Google Sheet will be reflected in our browser.

That’s it. Add some design and you have a simple application built on real-time data from Google Sheets. Remember, any data we are using is technically “public” so anybody with the link would have read access.

Let’s review what we covered in this tutorial:

  • Setting up create-react-app
  • Publishing a Google Sheet to the web
  • Using Tabletop.js to send a JSON object to our react application
  • Rendering the Google Sheet data in react
  • Handling real-time updates made in Google Sheets

Overall, the technical aspect of this tutorial is relatively simple. There are definitely ways we can take the core concepts and expand to make a meaningful application. One example I’ve personally used is adding the layer of Google Forms. Any Google Form has the ability to export responses to a google sheet. By exporting to Google Sheets you can now send out a simple Google Form and send the responses to your react application in real-time.

As someone who worked mainly in Excel/Google Sheets prior to programming, I was always looking for techniques to display data in a custom way. If you’re starting out as well, I hope this tutorial gives you some inspiration for new projects.

Link to Github repo:

https://github.com/ryanMcNierney/React-GoogleSheets

--

--

Responses (12)