作った話4

PWAでtoDo(にちょっと毛が生えた)アプリを作った_④アプリにデータを保存する〜ハダカのindexedDB編〜

こんにちは。このシリーズは、PWAでtodoアプリっぽいものを作った備忘録のようなものです。人によって役に立つ部分とそうでない部分があると思いますので、見繕って読んでいただければ幸いです。

ちなみに、作ったアプリは以下です。ぜひお試しを。

そして、今までの記事はこちら


さて、今回はいよいよアプリ本体の制作に入ります。

アプリにデータを保存するために、

indexedDB

というのを使っていきます。

が、

今回はあくまでデモンストレーションというか、「とにかくindexedDBを使ってみる」というノリで、次回にindexedDBをもっと使いやすくするライブラリ(lovefieldというやつです)を使っていきますので、ぶっちゃけ今回のは『ありがとログ』の中では動いておりません。

基本としてまずはハダカのままのindexedDBを扱ってみるという内容なので、流し見程度に読んでいただければ幸いです。

前提としている環境は

・create-react-appで作成したreactのプロジェクト

なので、それを踏まえて。でも vue だろうがフレームワークなしだろうがそんなに変わらないと思います。たぶん。

それではいきましょう。

indexedDBとは…

大量のオブジェクトを格納できるローカルデータベース

ということらしいです。

localStrageとの違いは、

・保存できる容量が多い(ブラウザとデバイスの状況によるが、少なくとも50MBぐらいはいけるみたい)
・JSON形式で保存可能(localStrageは文字列形式

ということらしい。

というわけで、アプリを作るならindexedDBをメインに使うのが正解だと思います。todoアプリ程度なら何の懸念もなさそう。


実際に使ってみる

まずは、indexedDBを使うためのjsファイルを用意して、index.jsから読み込みます。場所はpublic以下ならどこでも。

今回は、

public/src/indexedDB/indexedDB.js

としておきます。

そして、index.jsからimportです。

//indexedDB
import './indexedDB/indexedDB.js';

これで準備はできたので、indexedDB.jsをいじっていきます。

DBを設定

まずは、DBを作成しましょう。indexedDBに以下を書いて実行します。

//DBの名前を定義する。好きな名前をつけてください。
const demoDbName = 'demoIndexedDB';

//バージョン この数値が以前の数値より高ければ、更新用のメソッドが動く。
//現在の日付にしておけば管理しやすいと思います。
const version = 201903021636;

//DBのオープン(DB名とバージョンを渡す)
const openReq  = indexedDB.open(demoDbName,version);

とりあえずここまで。chromeのdevtoolで確認してみましょう。

できていますね。よしよし。それでは次のステップへ。


DBの更新・バージョンアップ

DBにストア(RDBにおける「テーブル」のようなもの)を追加したり、削除したりするには、openReq.onupgradeneededつーのを使います。

まずは、ちょっと試してみます。

indexedDB.jsに以下を書き足します。さっきの続きです。openReqはさっき定義したやつなので、定数名を変えてたらそのように。

openReq.onupgradeneeded = (event) => {
    console.log('onupgrandeneeded_works!');
}

実行してconsoleをみてみます。

出ました。そしたら、ここで一度リロードしてみます。

出ませんね。何度リロードしても出ません。

そしたら今度は、さっきのversionの値をいじってみましょう。さっきより大きい値に設定しなおしてください。

const version = 201903021641;

実行。

でた。こういうことですね。バージョンをアップすると動くわけです。

というわけで、このメソッドの中でオブジェクトストアを作ったりしていきます。


オブジェクトストアの作成

まずは、オブジェクトストアを作成してみます。

RDBでいうところのテーブル。だそう。

今回は"Fruits"というストアを作ってみます。コードはこちら。

//objectStoreNames
const fruitsStoreName = 'Fruits';

//DBバージョンアップ
openReq.onupgradeneeded = (event) => {
    //DBの定義
    const openedDB = event.target.result;

    if(openedDB.objectStoreNames.contains(fruitsStoreName) === false){
        //Fruitsというオブジェクトストアがなければ作る

        //createObjectStore()の第一引数にストアの名前、第二引数に設定のオブジェクト
        //この場合”id”を各データのkeyにして、データ登録時に自動で連番になるように設定
        openedDB.createObjectStore( fruitsStoreName , {keyPath : 'id',autoIncrement: true});
    }
}

オブジェクトストアの名前を定数に入れておき、openReq.onupgradeneededを動かします。

その中で、createObjectStore()というメソッドで、ストアを作ります。第一引数にストア名、第二引数に設定オブジェクトを入れます。

この場合”id”をkeyにして、データ登録時に自動で連番になるように設定しています。

さて、リロードしてみましょう。バージョンをアップするのを忘れずに。

できました。

ここに、データを挿入していくわけです。


データの挿入

作ったFruitsストアにフルーツのデータをぶち込んでみましょう。

まずはこちらをindexedDB.jsに追加してみます。

openReq.onsuccess = (event) => {
    //onupgradeneededの後に実行。更新がない場合はすぐに実行される。
    console.log('db open success');
    const openedDB = event.target.result;

    // 接続を解除する
    openedDB.close();
}

こいつは、onupgradeneededの後に実行されます。バージョンの変更がなければ、すぐに実行。要は、いつも動くやつです。

チェック。

サクセスしてますね。

とりあえずここに、データ挿入のスクリプトを書いて試すことにします。

まずはコードを

openReq.onsuccess = (event) => {
    //onupgradeneededの後に実行。更新がない場合はこれだけ実行
    console.log('db open success');
    
    const openedDB = event.target.result;

    //ここから追加
    
    //試しに挿入するデータ
    const fruitData = {name:'banana',price:150};

    //transaction
    const trans = openedDB.transaction(fruitsStoreName, 'readwrite');
    //store
    const store = trans.objectStore(fruitsStoreName);
    //挿入、編集のリクエストをする(addにすれば挿入のみ)
    const putReq = store.put(fruitData);

    //データの挿入成功時に実行
    putReq.onsuccess = (event) => {
        console.log(event.target.result);
    }

    //putReq.onsuccessの後に実行
    trans.oncomplete = () => {
        console.log('transaction完了');
    }

    //ここまで追加

    // 接続を解除する
    openedDB.close();
}

データを設定して、トランザクションを生成して、ストアを定義して、追加リクエストという流れです。

さて、結果はどうなるかを見ます。

あれ、追加されてない。と焦るなかれ。refreshが必要です。

上の画像で、Networkタブの下にあるrefreshボタンをクリック。

ちゃんと追加されてました。ちなみに、onsuccess()の中に書いてあるので、リロードしたらしただけ

追加されちゃいます。

本番のアプリでは、クリックイベントやその他のなんらかのイベントでこのへんの処理を動かすことになるでしょう。

データの削除・取得

挿入のリクエスト部分を変えてあげればできます

・削除

//引数には削除したいkeyを指定してください。この場合id:1を削除です
const delReq = store.delete(1);

delReq.onsuccess = (event) => {
    console.log(event.target.result);
}

・取得

//引数には取得したいkeyを指定してください。この場合id:4を取得です
const getReq = store.get(4);

getReq.onsuccess = (event) => {
    console.log(event.target.result);
}

こんなかんじ。

ほかにもいろいろなので、ここを見るといいかんじ。


オブジェクトストアの削除

作ったものは壊しましょう。というわけで。

openReq.onupgradeneededの中身を書き換えます。

//DBバージョンアップ
openReq.onupgradeneeded = (event) => {
    //DBの定義
    const openedDB = event.target.result;
    
    //オブジェクトストアの削除
    openedDB.deleteObjectStore( peopleStoreName );

}

バージョンアップを忘れずに。

消えました。

データベースの削除

消しちゃいましょう。忘れましょう。

//DBの名前を定義する
const demoDbName = 'demoIndexedDB';

const deleteReq  = indexedDB.deleteDatabase(demoDbName);

はい。

さよなら〜。


まとめ

indexedDBでブラウザにデータを保存、削除する一連をやってみました。

これをいい感じに駆使してアプリを作っていくわけですね。

でも、

はじめに言った通り、もっと便利に管理できるライブラリがあるのでそちらを使っていきます。

この記事のことは参考までに。


これだけ覚えて帰ってください

・indexedDBは、大容量かつJSON形式でブラウザにデータを保存できる
・indexedDBを便利に使えるライブラリがあるので、そっちを使おう


また次回。


参考リンク

ぶっちゃけ今回の内容、このページ見ればいいのでした。


お叱り、ご指摘、マサカリなどはこちらへお願いします。


この記事が気に入ったらサポートをしてみませんか?