深入了解 Airtable API

Avatar of Robin Rendle
Robin Rendle

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 $200 免费赠送额度!

Airtable 网络应用程序非常棒。您可以将其用作电子表格,但它对于各种其他用途也同样有用。对我来说,最棒的一点是它有一个 API,因此您可以将其视为数据库。

我一直想为我在 Gusto 工作的不同团队制作每周笔记,以便他们了解设计系统团队正在进行的工作,我们修复的内容以及我们在工作过程中遇到的任何可能影响我们组织中其他设计师和工程师的错误。我花了几小时思考如何使用 Airtable 收集大量数据,然后使用其 API 提取这些信息并将其显示在网络应用程序中。

以下是一个示例,说明我们最终将构建的内容,它基本上是一个使用 Airtable 作为一种巧妙的 CMS 的 React 网络应用程序

首先,我们需要转到命令行并运行以下命令(但首先确保已安装 npm)

npx create-react-app airtable-test

这将创建一个名为 airtable-test 的新目录,我们将在这里创建我们的 React 应用程序。如果我们在此安装完成后在命令行中运行 yarn start,那么我们将看到该项目的默认页面

并且,如果我们打开 airtable-test 目录中的 src/App.js,我们可以看到此页面是如何使用 React 呈现的

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
     <div>
       <header>
         <img src="{logo}" alt="logo" />
         <p>Edit src/App.js and save to reload.</p>
         <a href="https://reactjs.ac.cn" target="_blank" rel="noopener noreferrer">Learn React</a>
       </header>
     </div>
    );
  }
}

export default App;

现在我们已经启动并运行了 React,我们可以继续在命令行中安装 airtable,这将使我们能够与 Airtable API 交互

npm i airtable

完成此操作后,我们需要创建一个 Airtable 帐户并创建一个项目。最终我们将得到类似于以下电子表格的内容

A screenshot of a spreadsheet. The header is a bright orange and the sheet contains four rows and four columns of content, ordered by date.

现在,我们可以转到 airtable.com/api 并选择我们的项目,以便它充当我们从中提取数据的来源。在本例中,我选择了“设计系统项目”,您可以在此处底部看到

这将把我们带到一个方便的文档网站,该网站为我们提供了针对特定项目的非常易于阅读的 API!向下滚动,我们会找到我们的 API 密钥,我们需要使用它来访问此数据以及可以用来操作我们获取数据的许多示例

A screenshot of the Airtable API webpage. The heading says Standard API and a list of options, including example projects, is provided. Below the example projects is the project configured in this post, called Design Systems Project.

让我们回到 airtable-test 目录中的 App.js,删除该文件中的所有代码,并将其替换为以下内容

import React, { Component } from 'react';
import Airtable from 'airtable';
const base = new Airtable({ apiKey: 'XXXXXXXXXXX' }).base('XXXXXXXXXXX');

确保将这些 X 替换为您在刚打开的 Airtable API 文档中看到的详细信息。但是,现在我们已经完成了所有设置,我们终于可以开始创建我们的界面了,方法是从我们的电子表格中调用数据。

App.js 中,我们可以开始构建 App 组件

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      records: []
    };
  }
  render() {
    return {<div>Hello</div>}
  }
}

目前,这将做的只是设置应用程序的状态,然后在页面上渲染“Hello”。接下来,我们将向该状态添加 Airtable 中的每个记录。

首先要重点注意的是:在 componentDidMount() 中,我们将选择 Updates,这只是告诉 Airtable 我们想要名为 Updates 的电子表格的一种方式。确保此名称与电子表格的名称相同。我们还将在该函数中循环遍历表格中的所有记录或行

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      records: []
    };
  }
  componentDidMount() {
    base('Updates').select({view: 'Grid view'})
    .eachPage(
      (records, fetchNextPage) => {
        this.setState({
          records
        });
        console.log(records);
        fetchNextPage();
      }
    );
  }
  render() {
    return (
     <div>
       <div>Hello</div>
     </div>
    )
  }
}

fetchNextPage() 是 Airtable API 为我们提供电子表格中下一条记录的方式,它很巧妙的是,它会一直继续下去,直到没有更多记录为止。同样,我们还没有对这些数据进行任何操作;我们只想确保在此时一切都正常运行。

打开 DevTools 中的控制台,我们应该会看到类似于以下内容

Array(4) [ {…}, {…}, {…}, {…} ]

如果我们深入研究此数组中的每个对象,那么我们应该会找到电子表格中的所有数据!对我来说,做这一部分总是感觉很神奇。

无论如何,接下来我们可以像这样更新我们的 render() 函数

render() {
  return (
   <div>
     {this.state.records.length > 0 ? ( this.state.records.map((record, index) =>
       <div>
         <h2>{record.fields['Date']}</h2>
         {record.fields['UI Kit']} {record.fields['Component Library']}
       </div>
      ) ) : (
        <p>Loading...</p>
      )}
    </div>
  )
}

我们现在将循环遍历我们之前设置的状态,然后渲染电子表格中每一列的 record.fields[]。我们有一个日期、UI 工具包和组件库列,并且在使用上面的代码更新了 App.js 之后,我们应该会看到电子表格中的所有内容!

A screenshot of a default webpage with no styling with four headings containing dates in year/month/day numeric format following by a block of text containing content from the spreadsheet.

这就像魔法一样!但是,为什么这些数据看起来如此奇怪呢?嗯,这是因为我想在每个单元格中编写 Markdown,所以现在我们需要使用解析器将这些数据转换为传统的 HTML。首先,我们需要回到命令行

npm i showdown 

showdown 将帮助我们解析我们在 Airtable 电子表格中编写的所有 Markdown。安装完成后,我们只需要在 App.js 文件顶部导入它,如下所示

import showdown from 'showdown';
const markdownConverter = new showdown.Converter();

componentDidMount() 函数之后,我们可以创建一个使用 showdown 创建 HTML 的另一个函数

createHTML(markdown){
  return(
    markdownConverter.makeHtml(markdown)
  )
}

它有点不稳定,但它让我感觉代码更整洁一些。现在我们可以更新我们的 render() 函数

  render() {
  return (
    <div className="App">
      {this.state.records.length > 0 ? (
        this.state.records.map((record, index) =>
          <div key={index}>
            <h2>{new Date(record.fields['Date']).toISOString().split('T', 1)}</h2>
            <div dangerouslySetInnerHTML={{__html: this.createHTML(record.fields['UI Kit'])}} />
            <div dangerouslySetInnerHTML={{__html: this.createHTML(record.fields['Component Library'])}} />
          </div>
        )
      ) : (
        <p>Loading...</p>
      )}
    </div>
  );
}

我们在这里做了一些新的事情:我们正在每个 div 中使用 dangerouslySetInnerHTML,它反过来使用我们的 createHTML 函数将每列(特别是 UI 工具包和组件库列)中的数据转换为 HTML。我们还将每行的日期转换为标题,以便更容易阅读。

这样一来,我们基本上就完成了!这是最终的 App.js

import React, { Component } from 'react';
import Airtable from 'airtable';
import showdown from 'showdown';

const markdownConverter = new showdown.Converter();

const base = new Airtable({ apiKey: 'xxxxxxx' }).base('xxxxxxx');

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      records: []
    };
  }
  componentDidMount() {
    base('Updates').select({view: 'Grid view'})
    .eachPage(
      (records, fetchNextPage) => {
        this.setState({
          records
        });
        fetchNextPage();
      }
    );
  }
  createHTML(markdown){
    return(
      markdownConverter.makeHtml(markdown)
    )
  }
  render() {
    return (
      <div className="App">
        {this.state.records.length > 0 ? (
          this.state.records.map((record, index) =>
            <div key={index}>
              <h2>{new Date(record.fields['Date']).toISOString().split('T', 1)}</h2>
              <div dangerouslySetInnerHTML={{__html: this.createHTML(record.fields['UI Kit'])}} />
              <div dangerouslySetInnerHTML={{__html: this.createHTML(record.fields['Component Library'])}} />
            </div>
          )
        ) : (
          <p>Loading...</p>
        )}
      </div>
    );
  }
}

export default App;

我们仍然可以进行大量更新来改进它。我初步尝试了样式设置,但我们可能想要做一些事情,例如改进日期格式,并可能添加某种指示来指示哪些更新指的是电子表格中的哪些行。也许我们甚至可以切换显示哪些信息,具体取决于您是设计师还是工程师。

An animating screenshot of the final result which contains the same content as the earlier example but with extra spacing between sections and the column headings in dark orange and flushed to the left of the content instead of above it.

无论如何!我认为这是一个开始深入了解 Airtable API 的好方法,我很乐意在下面的评论中了解您是如何使用它的。