Closed1

DexieのuseLiveQueryをクラスコンポーネントで使いたい

TakeTake

DexieのuseLiveQuery
https://dexie.org/docs/dexie-react-hooks/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
質問の回答としてはコンポーネントの外でliveQueryを定義して、

  • componentDidMountで監視可能なliveQuery()にサブスクライブ
  • componentWillUnmountでサブスクライブを解除

という実装で動くよう。

作成中のクラスコンポーネントではcomponentDidMount()は使っていないため、
useEffectでcomponentDidMountcomponentWillUnmountに相当する実装を行った。
https://qiita.com/takujiro_0529/items/1ddd5284692d52ac6be9

完成型↓

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

// 略

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

export const useXXX = () => {
  const [selectedNo, setSelectedNo] = React.useState(false);
  const [table, setTable] = React.useState([]);
  // indexedDBの読み込み
  React.useEffect(() => {
    const subscription = observableDb(selectedNo).subscribe(
      result => setTable(result),
      error => setTable([])
    )
    return () => {
      subscription.unsubscribe();
      setTable([]);
    }
  }, [selectedNo]);
// 略
このスクラップは2022/07/13にクローズされました