Fetch data with the Airtable API and display it in a React app with hooks

JB
Level Up Coding
Published in
7 min readJan 21, 2021

--

Airtable is a spreadsheet app with a free, public API. That allows its spreadsheets to be read and written to from the browser, making it usable as a simple database. This article will show how to fetch, create, update, and delete data from Airtable. The API calls will be handled by Axios, the popular library for handling HTTP requests.

Dependencies:

npm i axios — the Axios library for calling Airtable from the browser

npm i airtable — the package for configuring an Airtable base in React

Steps covered:

  1. Set up an Airtable base.
  2. Authenticate the base in React.
  3. Fetch data from a React custom hook with a GET request.
  4. Display it in React components.
  5. Protect your Airtable credentials.

This guide will describe Airtable-specific conventions. If you’re just interested in displaying data in React using Axios but aren’t using Airtable, this article describes it in detail.

1. Set up an Airtable base

Airtable refers to each instance as a base. A base is may contain multiple tables, which are a single spreadsheet. In the default workspace, I choose + Add a base, and Start from scratch.

I named my new base “database”. In the spreadsheet, the table is named Table 1 by default. We will have to query this table, so to simplify the query string I changed its name to map. I’m going to add in some test data to use for designing a map. Each row represents a different zone that could be classified on the map. This data isn’t important.

A word about data types in Airtable fields: they are very important. Your data will not display correctly, or at all, in the browser if the data types for your base’s columns don’t match their contents.

To change a field’s data type, click on the field heading and the Customize data type item. A menu of data types will open. Select the relevant one.

A note: many of these data types map neatly onto their JavaScript counterparts, e.g. “single line text” and “long text” for strings, “checkbox” for Boolean, date for the Date object, etc. The array data type is less obvious: To create an array, use the “Multiple select” data type. My “shades” column above is a multiple select list because I will render the values as an array.

The credentials from Airtable must be input into React to successfully make calls to Airtable without getting a 401: Unauthorized error in return.

Airtable gives you two main pieces of information to authenticate your account:

  • API key: The string used to authenticate your account account to Airtable when you call it with a request — This piece of information is as sensitive as your account password.
  • Base ID: The string used to identify the base you’re querying in your request. (One account may have many bases, each with a unique base ID.)

To get the credentials needed for React, go to https://airtable.com/api, and select your base. Here, you can find your API key and Base ID.

2. Authenticate the base in React

All authentication will happen in one place: the index.js file in React. This can happen in any component, but it’s neatest to keep it in one central area.

By using axios defaults, we can set the Airtable endpoint as the default endpoint to call. The Airtable endpoint is made of three parts:

https://api.airtable.com/v0/BASE_ID/table/
  • The Airtable URL, which must be HTTPS, not HTTP.
  • The base ID
  • The table within the base you’re calling—it’s the tab of the spreadsheet

To initialize Airtable, we create a new Airtable object and confirm our API Key and base — This is what the Airtable package allows.

> index.js

//create a new Airtable object in React 
new Airtable({apiKey:'API_KEY'}).base('BASE_ID');
//base endpoint to call with each request
axios.defaults.baseURL = 'https://api.airtable.com/v0/BASE_ID/map/';
//content type to send with all POST requests
axios.defaults.headers.post['Content-Type'] = 'application/json';
//authenticate to the base with the API key
axios.defaults.headers['Authorization'] = 'Bearer API_KEY';

3. Fetch data from Airtable

We want to call our data on page load. The GET request itself will happen in a custom hook, but we will call the function inside our component.

> Landing.js

import React, { useEffect } from 'react';
import useData from '../hooks/useData';
import Table from '../sections/Table';
export default function Landing() { const { data, getData } = useData(); useEffect(() => {
async function onPageLoad () {
await getData();
}
onPageLoad();
}, []);
return(
<div className="page">
<h3>Airtable data</h3>
{data && <Table data={data}/>}
</div>
)
}

We have an async function inside of the useEffect hook, which is called on each pageload. We will examine the Table component in the return statement, which will display the data, later.

Note: The Table component is called conditionally. Because data fetching is asynchronous, there will be a period of time when the data is null . We only want the table to render when the data is not null.

> useData.js

import { useState } from 'react';
import axios from 'axios';
export default function useData() {
const [data, setData] = useState(null);

const getData = async () => {
return axios.get('/').then(res =>
setData(res.data.records);
});
}
return {
getData,
data
}
};

Console.logging the data gives us an array of eight items. If we open the first item, we see it is an object with the createdTime, the fields (from our base) and an id string.

Airtable adds the createdTime and id fields.

Note that in our base, we don’t give the items a createdTime timestamp or a unique ID string. Airtable adds these to each row it returns. They can be useful for assigning each item a unique id or sorting by creation time, but we are going to remove them in the next step.

4. Display Airtable data in React components

Now we can use the Table component to display the data. To display it, I’m going to remove the id and createdOn properties that Airtable added, so I just have the fields object left. This is purely optional, but it makes it easier to work with the data.

Then, I’ll have an array of fields objects that I can map through and distribute into my data table:

> Table.js

import React from 'react';
import TableHeader from '../components/TableHeader';
const Table = ({data}) => { const fields = data.map(el => {
return el.fields;
})
return (
<table className="key">
<TableHeader
headings={['Zone', 'Name', 'Description', 'Shades']}/>
<tbody className="fullWidth">
{fields.map(el => {
return <tr key={el.zone} className="key__row">
<td className="key__cell">
<div className="key__color"
style={{background:el.color}}>
</div>
</td>
<td className="key__cell"
style={{fontWeight:'bold'}}>
{el.label}
</td>
<td className="key__cell">
{el.description}
</td>
<td className="key__cell colorKey__layers">
{el.shades && el.shades.map(el => {
return <div className="colorKey__ex"
key={el}
style={{backgroundColor:el}}>
</div>
})}
</td>
</tr>
})}
</tbody>
</table>
);
}
export default Table;

I am little disappointed with how clunky this code is…but it’s not a beauty contest.

Note: to display an array on Airtable you have to wait for the array, just as you wait for an asynchronous response. I’m not sure why—it might be a quirk of how they return data. Look at how I wait for el.shades before mapping it.

The mapped table looks like this:

5. Protect your credentials

If you deploy a public site where you call the Airtable API directly from the frontend, you can expose your Airtable API key. This will compromise the security of your data. Some solutions for this, listed from easiest to hardest to implement:

  1. Airtable recommends creating a read-only user and making that API key the one used, so if anyone gets access to it, they cannot modify your data.
  2. The API key can be obscured in an environmental variable.
  3. Create a backend server and call Airtable through there (note: the key would still have to be obscured if you make the code open source).

--

--