2019/05/06 (增加範例程式)
2019/07/22 (增補資料)
Airtable是個雲端服務,提供類似試算表的資料庫,可以利用airtable提供的javascript library或者利用REST存取資料。在這邊先介紹如何透過REST存取資料。
react可以利用javascript內建的fetch來呼叫RESTful web services,也可以利用Axios,採用Axios的好處是,Axios會自動處理json的內容 (詳參: Fetch vs. Axios.js for making http requests)。
首先,先安裝axios
npm install axiosindex.js
import React from 'react';import ReactDOM from 'react-dom';import './index.css';import ReactApp from './components/react-app';import * as serviceWorker from './serviceWorker';ReactDOM.render(<ReactApp />, document.getElementById('root'));// If you want your app to work offline and load faster, you can change// unregister() to register() below. Note this comes with some pitfalls.// Learn more about service workers: https://bit.ly/CRA-PWAserviceWorker.unregister();連接airtable,是透過Bearer token,所以,要設定header,並將airtable的API取代程式中的XXXXXXXXXXXXXXXXX。
Authorization: 'Bearer XXXXXXXXXXXXXXXXX'也要將appLNbQOB0WL1ZeDD取代為你的Base id,Table%201,取代為你的table名稱,如果table名稱有空白,就要用%20取代(URI Encode)。
constructor(props) { super(props); this.state = {students: []}; this.Axios = axios.create({ baseURL: "https://api.airtable.com/v0/appLNbQOB0WL1ZeDD/Table%201?view=Grid%20view", headers: {'Authorization': 'Bearer XXXXXXXXXXXXXXXXX'} }); }取得的資料格式:
{ "records": [ { "id": "rec6USTCW7WQS1D4H", "fields": { "City": "台北市", "Age": 8, "Name": "Ben" }, "createdTime": "2019-03-08T06:18:45.000Z" }, { "id": "recM3qifn7g8hlLhy", "fields": { "City": "新北市", "Age": 6, "Name": "Ana" }, "createdTime": "2019-03-08T06:18:45.000Z" }, { "id": "rec9yMWV1aqzQv0g3", "fields": { "City": "台北市", "Age": 7, "Name": "Mary" }, "createdTime": "2019-03-08T06:18:45.000Z" } ], "offset": "rec9yMWV1aqzQv0g3"}因為資料會包在records裡,所以,取得資料時,要多records
componentDidMount() { let _this = this; this.Axios.get() .then(function (response) { console.log(response); _this.setState({students: response.data.records}); }) .catch(function (error) { console.log(error); });components/react-app.js
import React from 'react';import axios from 'axios';import StudentList from './student-list' export default class ReactApp extends React.Component { constructor(props) { super(props); this.state = {students: []}; this.Axios = axios.create({ baseURL: "https://api.airtable.com/v0/appLNbQOB0WL1ZeDD/Table%201?view=Grid%20view", headers: {'Authorization': 'Bearer XXXXXXXXXXXXXXXXX'} }); } componentDidMount() { let _this = this; this.Axios.get() .then(function (response) { console.log(response); _this.setState({students: response.data.records}); }) .catch(function (error) { console.log(error); }); } render() { return ( <div> <StudentList students={this.state.students}/> </div> ) }}components/student-list.js
import React from 'react';import Student from './student' export default class StudentList extends React.Component{ render() { var students = this.props.students.map((student, i) => <Student key={i} student={student}/> ); return ( <table> <tbody> <tr> <th>姓名</th> <th>年齡</th> <th>城市</th> </tr> {students} </tbody> </table> ) }}因為資料內容又包在fields中,取得時要加fields
student.js
import React from 'react'; export default class Student extends React.Component{ render() { return ( <tr> <td>{this.props.student.fields.Name}</td> <td>{this.props.student.fields.Age}</td> <td>{this.props.student.fields.City}</td> </tr> ) }}import React from 'react';import axios from 'axios';export default class StudentAdd extends React.Component{ handleChange=(event)=>{ this.setState({ [event.target.name]: event.target.value }); } handleSubmit=(event)=> { //event.preventDefault(); //console.log("Clicked!"); const student = {fields:{ Name: this.state.name, Age: Number(this.state.age), City: this.state.city } }; let axiosConfig = { headers: { Authorization: 'Bearer XXXXXXXX' , 'Content-Type': 'application/json' } } api.post("https://api.airtable.com/v0/appLNbQOB0WL1ZeDD/Table%201?view=Grid%20view", student, axiosConfig ) .then(res => { //console.log(res); //console.log(res.data); }) .catch(function (error) { //console.log(error); }); } render() { return ( <div> <form onSubmit={this.handleSubmit}> <label> Person Name: <input type="text" name="name" onChange={this.handleChange} /> </label> <label> Age: <input type="text" name="age" onChange={this.handleChange} /> </label> <label> City: <input type="text" name="city" onChange={this.handleChange} /> </label> <button type="submit">Add</button> </form> </div> ) }}利用airtable提供的功能,要先安裝airtable
npm install airtablestudent-list.js
import React, {useState, useEffect} from 'react';import Student from './student'import { Paper, Table, TableBody, TableHead, TableRow, TableCell } from '@material-ui/core/';import useStyles from './styles'; export default function StudentList() { const classes = useStyles(); const Airtable = require('airtable'); const base = new Airtable({apiKey: 'XXXXXXXXXXXXXXXXXX'}).base('appLNbQOB0WL1ZeDD'); const [students,setStudents] = useState([]); useEffect(()=>{ base('Table 1').select({view: "Grid view"}).all() .then(records => { setStudents(records); }).catch(err => { console.error(err); }); },[]) return ( <Paper className={classes.root}> <Table className={classes.table}> <TableHead> <TableRow> <TableCell>ID</TableCell> <TableCell>Age</TableCell> <TableCell>City</TableCell> </TableRow> </TableHead> <TableBody> {students.map((student, i) => <Student key={i} student={student}/>)} </TableBody> </Table> </Paper> )}styles.js
import { makeStyles } from '@material-ui/core/styles';const useStyles = makeStyles(theme => ({ root: { //width: '85%', marginTop: theme.spacing(3), marginLeft: theme.spacing(3), marginRight: theme.spacing(3), overflowX: 'auto', }, table: { minWidth: 650, }, }));export default useStyles;student.js
import React from 'react';import { TableRow, TableCell } from '@material-ui/core/'; export default function Student(props){ return ( <TableRow key={props.student.fields.Name}> <TableCell>{props.student.fields.Name}</TableCell> <TableCell>{props.student.fields.Age}</TableCell> <TableCell>{props.student.fields.City}</TableCell> </TableRow> ) }student-add.js
import React,{useState} from 'react';//import axios from 'axios';import { Paper,TextField, Button } from '@material-ui/core/';import useStyles from './styles';// https://rangle.io/blog/simplifying-controlled-inputs-with-hooks/export default function StudentAdd(){ const Airtable = require('airtable'); const base = new Airtable({apiKey: 'XXXXXXXXXX'}).base('appLNbQOB0WL1ZeDD'); const [name,setName] = useState(""); const [age,setAge] = useState(0); const [city,setCity] = useState(""); const classes = useStyles(); const handleSubmit=(event)=> { //event.preventDefault(); const student={ Name:name, Age:Number(age), City:city}; base('Table 1').create(student , function(err, record) { if (err) { console.log(err); return; } console.log(record.getId()); }); } return ( <div> <Paper className={classes.root}> <form onSubmit={handleSubmit}> <TextField id = "name" label="Person Name:" onChange={e=>setName(e.target.value)}/> <TextField id = "age" label="Age:" onChange={e=>setAge(e.target.value)}/> <TextField id = "city" label="City:" onChange={e=>setCity(e.target.value)}/> <Button variant="contained" type="submit" color="primary">Add</Button> </form> </Paper> </div> )}