🛠️

[React]DexieのuseLiveQueryをカスタムhookで使いたい

2022/07/13に公開

useLiveQueryとは

indexedDBの取得をカスタムhook化したもの
https://dexie.org/docs/dexie-react-hooks/useLiveQuery()

カスタムhookでやりたき事

  • アイテムを選択(ローカルstateで値を保存)
  • 選択したアイテムの情報をindexedDBから検索して返却

カスタムhookにuseLiveQueryを追加(失敗)

関数コンポーネントのサンプルをもとに、useLiveQuery()で取得したデータをsetSteteに代入しようとしたら、
戻り値がObservable<void>なので代入できません、というエラーがでた。

useXXX.ts
import React from "react";
import { useLiveQuery } from "dexie-react-hooks";

export const useXXX = () => {
  const [selectedNo, setSelectedNo] = React.useState(false);
  const [table, setTable] = React.useState([]);

  const friends = Database.db.annotations.where({ No: selectedNo}).toArray(
    React.useEffect(() => {
     setTable(friends);
// 略

原因

Dexieのissuesでクラスコンポーネントで使いたい場合の質問と回答を発見。
https://github.com/dexie/Dexie.js/issues/1231

  • useliveQueryは関数コンポーネント(表示するエレメントをreturnで返す)にしか使えないのでliveQueryを使う
  • componentDidMountで監視可能なliveQuery()にサブスクライブ
  • componentWillUnmountでサブスクライブを解除

という実装で動くよう。

作成中のhookではcomponentDidMount()は使っていないため、
useEffectでcomponentDidMountcomponentWillUnmountに相当する実装を行った。
https://qiita.com/takujiro_0529/items/1ddd5284692d52ac6be9

カスタムhookにuseLiveQueryを追加(成功)

useXXX.ts
import * as React from "react";
import { liveQuery } from "dexie";

// 略

// 引数にuseStateの値を使いたかったのでラップ
// 非同期にしないとobservableの戻り値がundifiendになった
const observableDb = (selectedNo) => {
  const observable = liveQuery(async () => {
    const returnValue = await Database.db.something.where({ No: selectedNo}).toArray();
    return returnValue;
  });
  return observable;
};

export const useXXX = () => {
  const [selectedNo, setSelectedNo] = React.useState(false);
  const [store, setStore] = React.useState([]);
  // indexedDBの戻り値をstateに保存
  React.useEffect(() => {
    const subscription = observableDb(selectedNo).subscribe(
      result => setStore(result),
      error => setStore([])
    )
    return () => { // componentWillUnmountに相当する
      subscription.unsubscribe();
      setStore([]);
    }
  }, [selectedNo]);// 第2引数を設定することでcomponentDidMountに相当する
// 略

Discussion