Chrome拡張機能のストレージを扱う時に@extend-chrome/storageが便利
どうも。えーたんです。
@extend-chrome/storageが便利なので紹介します。
@extend-chrome/storageとは?
@extend-chrome/storageは、Chrome拡張機能のAPIchrome.storage
のラッパーです。
メリットは以下の3つです。
- storageから取得した値の処理をコールバックではなくasync/awaitを使って書くことができる
- 型情報を追加できる
- ストレージをBucketとして区切ることができる
実際の例を交えて説明します。
まずはchrome.storage
をラッパー無しで使った例です。saveCount
でchrome.storage.local.set
を、loadCount
でchrome.storage.local.get
を使っています。
import { useState } from "react";
function App() {
const [count, setCount] = useState(0);
const saveCount = () => {
chrome.storage.local.set({ point: count });
};
const loadCount = () => {
chrome.storage.local.get(["point"], function (result) {
setCount(result.point);
});
};
return (
<div className="App">
<h2>@extend-chrome/storage Example</h2>
<div>
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
</div>
<div>
<button onClick={saveCount}>Save point</button>
<button onClick={loadCount}>Load point</button>
</div>
</div>
);
}
export default App;
次に、@extend-chrome/storageを使った例です。
import { useState } from "react";
import { getBucket } from "@extend-chrome/storage";
interface MyBucket {
point: number;
person: string;
color: string;
name: string;
}
const bucket = getBucket<MyBucket>("my-bucket");
function App() {
const [count, setCount] = useState(0);
const saveCount = () => {
bucket.set({ point: count, person: "eetann", color: "green" });
};
const loadCount = async () => {
const value = await bucket.get();
setCount(value.point);
};
// return以降は同様
分けて説明していきます。
chrome.storage
で値を保存・取得してから処理させる場合、コールバック内に書く必要がありました。@extend-chrome/storageを使えば、コールバックではなくasync/awaitを使って書くことができます。
- chrome.storage.local.get(["point"], function (result) {
- setCount(result.point);
- });
+ const value = await bucket.get();
+ setCount(value.point);
型が定義できるため、テキストエディタの補完も効きます。
+import { getBucket } from "@extend-chrome/storage";
+
+interface MyBucket {
+ point: number;
+ person: string;
+ color: string;
+ name: string;
+}
+
+const bucket = getBucket<MyBucket>("my-bucket");
getBucket
を使うことでストレージを"Bucket"として区切ることができるため、異なる構造のデータを扱う時に型を分けて定義できます。以下の例では「MyBucketA
型のデータを保存するBucketbucket-a
」と「MyBucketB
型のデータを保存するBucketbucket-b
」の2つを定義しています。
const bucketA = getBucket<MyBucketA>("bucket-a");
const bucketB = getBucket<MyBucketB>("bucket-b");
getの形式
getBucket
で定義したバケットから値を取得するget
は、引数の書き方によって返ってくる値が異なります。
getの引数が未指定の場合
get
の引数が未指定の場合、Bucket全体が返ってきます。
const value1 = await bucket.get();
console.log(value1)
{color: 'green', person: 'eetann', point: 5}
getの引数がstring配列の場合
get
の引数にstring配列を指定すると、指定したキーと対応する値のみが取り出せます。
const value2 = await bucket.get(["point", "person"]);
console.log(value2)
{person: 'eetann', point: 5}
getの引数が文字列の場合
get
の引数に文字列を指定すると、指定したキーと対応する値のみが取り出せます。
このようにキーを1つだけ指定しても、取得できる形式は{key: value}
です。
const value3 = await bucket.get("point");
console.log(value3)
{point: 5}
getの引数がオブジェクトの場合
引数にオブジェクトを指定した場合、そのオブジェクトの中で指定したキーがBucketに存在するかしないかで挙動が変わります。
キーがBucketに存在しない場合、引数で指定した値を返します。
キーがBucketに存在する場合、保存した値が取得できます。
const value4 = await bucket.get({name: "eetann"});
console.log(value4)
上記の例では、name
キーの値を取得しようとしています。すでにキーが存在していれば、Bucketに保存した値を取得できます。存在していない場合、引数で指定したeetann
が返ってきます。
キーの一覧も取得できる
getKeys
を使えば、キーの一覧を取得できます。
const keys = await bucket.getKeys();
console.log(keys);
['color', 'person', 'point']
デフォルトはlocalだけとsyncにもできる
getBucket
の第2引数が未指定の場合に対応するAPIはchrome.storage.local
ですが、sync
を指定した場合はchrome.storage.sync
になります。
const bucket = getBucket("my-bucket", "sync");
最後に
@extend-chrome/storageのgetBucket
のAPIは、set
やget
だけではなくremove
やclear
にも対応しています。
本記事で扱ったサンプルコードは以下のリポジトリにあります。
Discussion