Airtable As A Minimum Viable Database For Your ReactJs Project

March 2, 2018

In this guide, I'll show you how to use Airtable as a minimum viable database for your ReactJs project.

First, what's Airtable?

Airtable is a souped up version of Google sheets with a robust API. Airtable is built for teams and is used to organize data rather than calculate things.

It's easy to make API calls to Airtable endpoints to push and fetch data to and from your Airtable base (spreadsheet).

I'll assume you're starting with a brand new ReactJs project. Here's the companion Github repo for this project that demonstrates how you can integrate Airtable into your React app.

We'll be using Airtable's API client-side, but you wouldn't want to do this in production because you'd exposure your API keys.

If you haven't already, install creat-react-app globally:

npm install -g creat-react-app

Issue the following to start a new project:

create-react-app my-app

First, install fetch (npm install whatwg-fetch --save).

cd my-app
npm i whatwg-fetch --save

Here's a quick refresher on fetch and async/await syntax:

const apiRequest = async () => {
  const resp = await fetch(url)
  // convert response to json
  const json = await resp.json()
}

Remember, you can only await a promise if the enclosing function is async.

Using Fetch With Airtable

We will make the API call to Airtable using fetch inside the componentWillMount() lifecycle component.

You can find your Airtable API key and endpoints at https://www.airtable.com/api.

Airtable endpoints look something like:

var url = `https://api.airtable.com/v0/${base}/${table}?maxRecords=20&view=${view}`;
import 'whatwg-fetch';
class App extends React.Component { ...
  async componentWillMount() {
    const key = 'YOUR API KEY';
    const url = 'YOUR AIRTABLE URL';
    const resp = await fetch(url, {
      headers: {
        "Authorization": `Bearer ${key}`
      }
    })
    const json = await resp.json()
    const {records} = resp
    console.log(records); 
  }
}

Now when you reload the page and check the console, you'll see your Airtable records logged.

Client-Side vs Server Side

You wouldn't want to do this in production because it would expose your API key to anyone who felt like viewing source.

The workaround is to make the final API calls to Airtable on the server-side.

For this example, we'll assume you're running Express with your ReactJs App.

Setting Up Express

Install node-fetch, express, and bodyParser:

npm install node-fetch express body-parser --save

In your project directory:

touch server.js

Add the following to server.js:

import express from 'express';
import bodyParser from 'body-parser';
import fetch from 'node-fetch';
const app = express();
app.get('/get', bodyParser.json(), async (req, res) => {
  const key = 'YOUR API KEY';
  var resp = await fetch('YOUR AIRTABLE URL ENDPOINT', {
    headers: {
      "Authorization": "Bearer: " + key
    }
  }) 
  const json = await resp.json()
  const {records} = resp;
  res.json({records});
});
app.use('/', express.static('public'));
app.listen(process.env.PORT || 3000);

This enables us to make the request to Airtable server side, in our express config file.

Now inside our React component, we make a get request to our same-origin '/get' endpoint, using fetch:

componentWillMount() {
  fetch('/get', {
  }).then(resp => resp.json())
  .then(resp => {
    const records = records;
    console.log(records);
  });
}

To summarize:

  1. We're making our API call to Airtable using node-fetch (don't forget to install it with npm install node-fetch --save).
  2. We're making a same-origin request to our custom defined endpoint '/get' (this is arbitrary - it could be '/sandwiches'). This allows the client-side to access our Airtable records that have been fetched server side.
  3. So far, all we've done is console.log our Airtable records. Here you may want to store you records in state.

To store your Airtable records in state, you would just define a new initial state as follows:

import React from 'react';
import 'whatwg-fetch';
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      airtable: []
    }
  ...
  }
}

And then inside your fetch request in componentWillMount replace the line console.log(records); with something like this:

this.setState({airtable: records});

Now this.state.records is a an array objects, where each object corresponds to a row in your Airtable.

It looks something like this:

records = [
  {
    field_1: "value_1",
    field_2: "value_2"
  }, 
  {
    field_1: "another value"
    field_2: "yet another"
  }
]

Since the records are an array of objects where each object corresponds to an Airtable row, we will use the map function to iterate through the array.

Here's an example:

...
render() {
    const airtable = this.state.airtable;
    const entry = airtable.map((airtable, index) =>
      <tr>
      <td>{airtable.fields.YOUR_FIELD_HERE}</td>
      <td>{airtable.fields.YOUR_OTHER_FIELD}</td>
      </tr>
    );
    return(
      <div><table><tbody>{entry}</tbody></table></div> 
  );
}

Checkout the complete working example here.