How to Use Airtable as a Cloud-Based Database for a React App

Table of Contents

  • Requirements
  • Setting up a New React app
  • Adding Material UI to React App
  • Create a Mock App
  • Loop through the Mock Data
  • Setting up Airtable
  • Fetching the Data from the Airtable API
  • Connect Crowdbotics platform to host your React + Airtable App
  • Conclusion

Requirements

  • Nodejs v8.x.x or higher installed along with npm/yarn.
  • create-react-app installed globally on your local dev machine to generate a new React project.
  • Free Airtable account and API key.

Setting up a New React app

create-react-app react-airtable-app

# or with npx

npx create-react-app react-airtable-app

Adding Material UI to React App

yarn add @material-ui/core
//App.js
import React from 'react'
import logo from './logo.svg'
import './App.css'
import Container from '@material-ui/core/Container'
import { makeStyles } from '@material-ui/core/styles'
import Card from '@material-ui/core/Card'
import CardActionArea from '@material-ui/core/CardActionArea'
import CardActions from '@material-ui/core/CardActions'
import CardContent from '@material-ui/core/CardContent'
import CardMedia from '@material-ui/core/CardMedia'
import Button from '@material-ui/core/Button'
import Typography from '@material-ui/core/Typography'

const useStyles = makeStyles({
card: {
maxWidth: 345
},
media: {
height: 180
}
})

function App() {
const classes = useStyles()

return (
<Container maxWidth='xs'>
<Card className={classes.card}>
<CardActionArea>
<CardMedia className={classes.media} image={logo} title='React' />
<CardContent>
<Typography gutterBottom variant='h5' component='h2'>
React + Airtable app
</Typography>
<Typography variant='body2' color='textSecondary' component='p'>
This card is built with create-react-app v3.0 and Material-ui v4.2.0
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button size='small' color='primary'>
Share
</Button>
<Button size='small' color='primary'>
Learn More
</Button>
</CardActions>
</Card>
</Container>
)
}

export default App

Create a Mock Card

import React from 'react'

import Container from '@material-ui/core/Container'
import { makeStyles } from '@material-ui/core/styles'
import Card from '@material-ui/core/Card'
import CardActionArea from '@material-ui/core/CardActionArea'
import CardActions from '@material-ui/core/CardActions'
import CardContent from '@material-ui/core/CardContent'
import CardMedia from '@material-ui/core/CardMedia'
import Button from '@material-ui/core/Button'
import Typography from '@material-ui/core/Typography'

const booksData = {
title: 'Pietr the Latvian',
author: 'Georges Simenon',
published: '1931',
description:
'Who is Pietr the Latvian? Is he a gentleman thief? A Russian drinking absinthe in a grimy bar? A married Norwegian sea captain? A twisted corpse in a train bathroom? Or is he all of these men? Inspector Maigret, tracking a mysterious adversary and a trail of bodies, must bide his time before the answer comes into focus.',
coverImage:
'https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1386339994l/19234594.jpg'
}

const useStyles = makeStyles({
gutterTop: {
marginTop: 20
},
card: {
maxWidth: 345
},
media: {
height: 350
}
})

function BooksCard() {
const classes = useStyles()

return (
<Container maxWidth='xs' className={classes.gutterTop}>
<Card className={classes.card}>
<CardActionArea>
<CardMedia className={classes.media} image={booksData.coverImage} title='React' />
<CardContent>
<Typography gutterBottom variant='h5' component='h2'>
{booksData.title}
</Typography>
<Typography variant='body2' color='textSecondary' component='p'>
by {booksData.author}
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button size='small' variant='outlined' color='disabled'>
{booksData.published}
</Button>
</CardActions>
</Card>
</Container>
)
}

export default BooksCard
import React from 'react'
import BooksCard from './components/BooksCard'

function App() {
return <BooksCard />
}

export default App

Loop through the Mock Data

const booksData = [
{
title: 'Pietr the Latvian',
author: 'Georges Simenon',
published: '1931',
description:
'Who is Pietr the Latvian? Is he a gentleman thief? A Russian drinking absinthe in a grimy bar? A married Norwegian sea captain? A twisted corpse in a train bathroom? Or is he all of these men? Inspector Maigret, tracking a mysterious adversary and a trail of bodies, must bide his time before the answer comes into focus.',
coverImage:
'https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1386339994l/19234594.jpg'
},
{
title: 'A Moveable Feast',
author: 'Ernst Hemingway',
published: '1964',
description:
'Begun in the autumn of 1957 and published posthumously in 1964, Ernest Hemingways A Moveable Feast captures what it meant to be young and poor and writing in Paris during the 1920s. A correspondent for the Toronto Star, Hemingway arrived in Paris in 1921, three years after the trauma of the Great War and at the beginning of the transformation of Europe cultural landscape: Braque and Picasso were experimenting with cubist form; James Joyce, long-living in self-imposed exile from his native Dublin, had just completed Ulysses; Gertrude Stein held court at 27 Rue de Fleurus, and deemed young Ernest a member of une gneration perdue; and T.S. Eliot was a bank clerk in London. It was during these years that the as-of-yet unpublished young writer gathered the material for his first novel The Sun Also Rises, and the subsequent masterpieces that followed.',
coverImage:
'https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1531210888l/4631.jpg'
}
]
import React from 'react'
import { makeStyles } from '@material-ui/core/styles'
import Card from '@material-ui/core/Card'
import CardActionArea from '@material-ui/core/CardActionArea'
import CardActions from '@material-ui/core/CardActions'
import CardContent from '@material-ui/core/CardContent'
import CardMedia from '@material-ui/core/CardMedia'
import Button from '@material-ui/core/Button'
import Typography from '@material-ui/core/Typography'
import Grid from '@material-ui/core/Grid'

const booksData = [
{
title: 'Pietr the Latvian',
author: 'Georges Simenon',
published: '1931',
description:
'Who is Pietr the Latvian? Is he a gentleman thief? A Russian drinking absinthe in a grimy bar? A married Norwegian sea captain? A twisted corpse in a train bathroom? Or is he all of these men? Inspector Maigret, tracking a mysterious adversary and a trail of bodies, must bide his time before the answer comes into focus.',
coverImage:
'https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1386339994l/19234594.jpg'
},
{
title: 'A Moveable Feast',
author: 'Ernst Hemingway',
published: '1964',
description:
'Begun in the autumn of 1957 and published posthumously in 1964, Ernest Hemingways A Moveable Feast captures what it meant to be young and poor and writing in Paris during the 1920s.A correspondent for the Toronto Star, Hemingway arrived in Paris in 1921, three years after the trauma of the Great War and at the beginning of the transformation of Europe cultural landscape: Braque and Picasso were experimenting with cubist form; James Joyce, long living in self-imposed exile from his native Dublin, had just completed Ulysses; Gertrude Stein held court at 27 Rue de Fleurus, and deemed young Ernest a member of une gneration perdue; and T.S. Eliot was a bank clerk in London. It was during these years that the as-of-yet unpublished young writer gathered the material for his first novel The Sun Also Rises, and the subsequent masterpieces that followed.',
coverImage:
'https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1531210888l/4631.jpg'
}
]

const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
margin: 20
},
gutterTopAndBottom: {
margin: 20
},
card: {
maxWidth: 345
},
media: {
height: 350
}
}))

function BooksCard() {
const classes = useStyles()

return (
<div className={classes.root}>
<Grid container direction='row' spacing={2}>
{booksData.map((bookItem, index) => (
<Grid item xs={3}>
<Card className={classes.card}>
<CardActionArea>
<CardMedia className={classes.media} image={bookItem.coverImage} title='React' />
<CardContent>
<Typography gutterBottom variant='h5' component='h2'>
{bookItem.title}
</Typography>
<Typography variant='body2' color='textSecondary' component='p'>
by {bookItem.author}
</Typography>
</CardContent>
</CardActionArea>
<CardContent>
<Typography paragraph variant='body2'>
{bookItem.description.length > 150
? bookItem.description.slice(0, 150) + `...`
: bookItem.description}
</Typography>
</CardContent>
<CardActions>
<Button size='small' variant='outlined' color='disabled'>
{bookItem.published}
</Button>
</CardActions>
</Card>
</Grid>
))}
</Grid>
</div>
)
}

export default BooksCard

Setting up Airtable

Fetching the Data from the Airtable API

import React from 'react'
import BooksCard from './components/BooksCard'
import Grid from '@material-ui/core/Grid'

class App extends React.Component {
state = {
booksData: []
}

componentDidMount() {
fetch('https://api.airtable.com/v0/appl7QOiAVWCczxPo/Table%201?api_key=YOUR_API_KEY')
.then(res => res.json())
.then(res => {
console.log(res.records)
this.setState({ booksData: res.records })
})
.catch(error => console.log(error))
}

// render function will come here
}

export default App
render() {
const {booksData} = this.state
return (
<Grid container direction='row' spacing={2}>
{booksData.map(book => (
<BooksCard {...book.fields} key={book.fields.id} />
))}
</Grid>
)
}
function BooksCard({ title, author, published, description, coverImage }) {
const classes = useStyles()
return (
<div className={classes.root}>
<Grid item xs={10}>
<Card className={classes.card}>
<CardActionArea>
<CardMedia className={classes.media} image={coverImage} title='React' />
<CardContent>
<Typography gutterBottom variant='h5' component='h2'>
{title}
</Typography>
<Typography variant='body2' color='textSecondary' component='p'>
by {author}
</Typography>
</CardContent>
</CardActionArea>
<CardContent>
<Typography paragraph variant='body2'>
{description.length > 150 ? description.slice(0, 150) + `...` : description}
</Typography>
</CardContent>
<CardActions>
<Button size='small' variant='outlined' color='primary'>
{published}
</Button>
</CardActions>
</Card>
</Grid>
</div>
)
}

Connect Crowdbotics platform to host your React + Airtable App

git init

# add all files
git add .

# commit
git commit -m "react-airtable-app"

Conclusion

Building A Web Or Mobile App?

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store