サクッとスマホアプリが作れるExpoでのSQLiteデータベースを使いたい時の話
Expoで使われるDBはfirebaseやmongoDBが多いようですが、
「とにかく楽に作ろうと思っているのに新しいこと覚えてられるか!」という僕みたいな人もいるはずだと思い、記録します。
環境
OS: ubuntu 16.04 LTS
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject",
"test": "jest"
},
"jest": {
"preset": "jest-expo"
},
"dependencies": {
"@expo/samples": "2.1.1",
"babel-core": "^6.26.3",
"babel-jest": "^24.1.0",
"babel-preset-env": "^1.7.0",
"expo": "^32.0.0",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"react-native-elements": "^1.1.0",
"react-navigation": "^3.0.9"
},
"devDependencies": {
"babel-preset-expo": "^5.0.0",
"jest-expo": "^32.0.0"
},
"private": true
}
導入
ExpoにAPIが用意されているので、それをimportするだけ。
import {SQLite} from 'expo'
データベース作成
const db = SQLite.openDatebase(name)
nameという名前のDBを取得します。
存在しなければ作ってくれます。
以降で用いるdatabaseオブジェクトをreturnするため、変数として定義する使い方になります。
SQL実行
createやselectのための関数は用意されておらず、全てSQLの実行でデータベース操作を行います。
以下のようなコードでSQLを実行します。
id, name の2つのカラムを持つ players テーブルを作成
const db = SQLite.openDatabase('db')
db.transaction(tx => {
tx.executeSql(
'create table if not exists players (id integer primary key not null, name text);', // 実行したいSQL文
null, // SQL文の引数
() => {console.log('success')}, // 成功時のコールバック関数
() => {console.log('fail')} // 失敗時のコールバック関数
);
},
() => {console.log('fail')}, // 失敗時のコールバック関数
() => {console.log('success')} // 成功時のコールバック関数
)
select文などの実行によりデータベース内のデータを取得し表示する、といった場合は、
executeSql
の第3引数(成功時のコールバック関数)に実装します。
データベースに登録された players を取得し、 state に格納
db.transaction(tx => {
tx.executeSql(
'select * from players',
null,
(_, { rows: { _array } }) => {this.setState({players: _array})} // 第2パラメータに格納されているクエリの結果から取得した配列(_array)を、stateに格納する
)
},
() => {console.log('fail')},
() => {console.log('success')}
)
実行例
Sato, Ito, Kato の3人の playerをテストデータとして insertし、
データベースから取得し表示しています。
import React from 'react';
import {SQLite} from 'expo'
import {
Text, View, FlatList
} from 'react-native';
import{
ListItem, Icon
} from 'react-native-elements'
const DB = SQLite.openDatabase('db')
function insertPlayer(name){
console.log('insert Player, name:' + name)
DB.transaction(tx => {
tx.executeSql(
`insert into players (name) values (?);`,
[name]
);
},
() => {console.log('fail')},
() => {console.log('success')},
);
}
function insertTestData(){
console.log('insertTestData')
insertPlayer("Sato")
insertPlayer("Ito")
insertPlayer("Kato")
}
insertTestData()
export default class HomeScreen extends React.Component {
constructor(props){
super(props)
this.state = {
players: null
}
}
componentWillMount(){
DB.transaction(tx =>{
tx.executeSql(
'create table if not exists players (id integer primary key not null, name text);'
),
null,
DB.transaction(tx => {
tx.executeSql(
'select * from players',
null,
(_, { rows: { _array } }) => this.setState({players: _array})
)
}
)
})
}
static navigationOptions = {
title: 'players'
};
render() {
const {players} = this.state
return (
<FlatList
data={players}
renderItem={({item}) =>{
return(
<ListItem
key={item.id.toString()}
title={item.name}
/>
)
}}
keyExtractor={item => item.id.toString()}
/>
);
}
}
参考文献
公式のAPIドキュメント
https://docs.expo.io/versions/latest/sdk/sqlite/
公式の使用例アプリケーション
https://github.com/expo/sqlite-example
さいごに
なにか間違いなどがあればご指摘お願いします。