如何跟踪dexie UseLiveQuery是否完成

问题描述 投票:0回答:3

我想在 UseLiveQuery 未完成时显示加载程序,并在 UseLiveQuery 返回空数组时显示“未找到组件”。

有没有简单的方法可以做到这一点?

非常感谢。

reactjs nest dexie
3个回答
6
投票

当您的查询器返回一个数组时,这是最简单的(见下文)。那么未定义的结果意味着仍在加载,而空数组意味着已完成加载但结果为零。

const friends = useLiveQuery (() => db.friends.toArray());
if (!friends) return <Spinner />; // Still loading

return <ul>{
  friends.map(friend => <li key={friend.id}>
    {friend.name}, {friend.age}
  </li>)
}</ul>;

但是,如果您的查询器从 table.get() 返回结果,则未定义的值可能意味着查询仍在加载或未找到请求的 id。为了区分两者,您可以让查询器返回一些内容,以便更容易区分两者。例如,让查询器将结果作为数组中的项目返回,并为 useLiveQuery() 提供第三个参数,并使用空数组(未定义的其他内容)作为默认结果。

const [friend, loaded] = useLiveQuery (
  () => db.friends.get(1).then(friend => [friend, true]),
  [], // deps...
  []  // default result: makes 'loaded' undefined while loading
);

if (!loaded) return <Spinner />; // Still loading...
if (!friend) return <NotFound ... />; // Loaded but friend not found

return <>{friend.name}, {friend.age}</>; // Loaded and friend found.

也就是说,在查询 indexedDB 时通常不需要微调器(除非非常复杂的查询)。在这种情况下,最好只返回

null
而不是
<Spinner />
,这样可以最小化最终用户的麻烦。


2
投票

我创建了一个包装器 (React) 钩子来通过 Dexie.js 提供这种行为。它完全使用 TypeScript 进行键入。 它还会考虑丢失的数据(例如,如果您 .get() 使用 IndexedDB 中不存在的键),并且在处理数组时具有不同的返回类型(因为在这种情况下,我们永远不会有未定义的数据结果)。

import {MySubClassedDexie, useDexieDb} from "@/providers/dexieProvider/dexieProvider";
import {useLiveQuery} from "dexie-react-hooks";

export enum Status {
    PENDING = 'pending',
    RESOLVED = 'resolved'
}

export type AsyncLiveQueryReturn<T = any> = AsyncLiveQueryReturnPending | AsyncLiveQueryReturnResolved<T>;

export interface AsyncLiveQueryReturnPending {
    isLoading: true;
    isSuccess: false;
    status: Status.PENDING;
    data: null;
}

export interface AsyncLiveQueryReturnResolved<T = any> {
    isLoading: false;
    isSuccess: true;
    status: Status.RESOLVED;
    data: T extends Array<infer U> ? Array<U> : (T | undefined);
}

const useAsyncLiveQuery = <T>(querier: (db: MySubClassedDexie) => Promise<T>, deps: any[] = [], defaultIfMissing?: T): AsyncLiveQueryReturn<T> => {
    const db = useDexieDb();

    const [data, status] = useLiveQuery(() => {
        return querier(db).then((data: T) => {
            const d = data === undefined ? defaultIfMissing : data;
            return [d, Status.RESOLVED]
        })
    }, deps, [null, Status.PENDING])


    return {
        isLoading: status === Status.PENDING,
        isSuccess: status === Status.RESOLVED,
        status,
        data,
    } as AsyncLiveQueryReturn<T>;
};

export default useAsyncLiveQuery;

您可以按如下方式使用它:

const {isLoading, isSuccess, data} = useAsyncLiveQuery(db => db.items.get(myId), [myId], myFallbackObject);

我希望这对某人有帮助!


0
投票

了解 Vue 中是否加载或未找到的简单方法:

const item = useObservable(Dexie.liveQuery(() => db.items.get(id.value).then(o => o || null)))

// Handle not found (undefined = still loading, null = not found)
watch(item, (newItem) => {
  if (newItem === null) {
    // HANDLE NOT FOUND
  }
})
© www.soinside.com 2019 - 2024. All rights reserved.