implement useStoreMessages

This commit is contained in:
Sasha 2023-02-21 23:42:08 +01:00
parent ac6b304774
commit b3e3a44420
No known key found for this signature in database
5 changed files with 94 additions and 13 deletions

View File

@ -5,7 +5,7 @@ export {
useCreateLightNode,
useCreateRelayNode,
} from "./useCreateWaku";
export { useFilterSubscribe } from "./useFilterSubscribe";
export { useFilterMessages } from "./useFilterMessages";
export {
FullNodeProvider,
LightNodeProvider,

View File

@ -7,7 +7,7 @@ export type HookState = {
error: undefined | string;
};
export type CrateWakuHook<T extends Waku> = HookState & {
export type CrateNodeResult<T extends Waku> = HookState & {
node: undefined | T;
};

View File

@ -5,7 +5,7 @@ import type { FullNode, LightNode, RelayNode, Waku } from "@waku/interfaces";
import type {
BootstrapNodeOptions,
CrateWakuHook,
CrateNodeResult,
FullNodeOptions,
LightNodeOptions,
RelayNodeOptions,
@ -19,7 +19,7 @@ type CreateNodeParams<N extends Waku, T = {}> = BootstrapNodeOptions<T> & {
const useCreateNode = <N extends Waku, T = {}>(
params: CreateNodeParams<N, T>,
): CrateWakuHook<N> => {
): CrateNodeResult<N> => {
const { factory, options, protocols = [] } = params;
const [node, setNode] = React.useState<N | undefined>(undefined);

View File

@ -1,20 +1,24 @@
import React from "react";
import type { IDecodedMessage, IDecoder, Waku } from "@waku/interfaces";
import type { IFilter, IDecodedMessage, IDecoder } from "@waku/interfaces";
import type { HookState } from "./types";
type UseFilterSubscribeParams = {
node: Waku;
type AbstractFilterNode = {
filter: IFilter;
};
type UseFilterMessagesParams = {
node: AbstractFilterNode;
decoder: IDecoder<IDecodedMessage>;
};
type UseFilterSubscribeResult = HookState & {
type UseFilterMessagesResult = HookState & {
messages: IDecodedMessage[];
};
export const useFilterSubscribe = (
params: UseFilterSubscribeParams,
): UseFilterSubscribeResult => {
export const useFilterMessages = (
params: UseFilterMessagesParams,
): UseFilterMessagesResult => {
const { node, decoder } = params;
const [error, setError] = React.useState<undefined | string>(undefined);
@ -32,8 +36,8 @@ export const useFilterSubscribe = (
let unsubscribe: null | (() => Promise<void>) = null;
setLoading(true);
node?.filter
?.subscribe([decoder], pushMessage)
node.filter
.subscribe([decoder], pushMessage)
.then((unsubscribeFn) => {
setLoading(false);
unsubscribe = unsubscribeFn;

77
src/useStoreMessages.ts Normal file
View File

@ -0,0 +1,77 @@
import React from "react";
import type {
StoreQueryOptions,
IStore,
IDecoder,
IDecodedMessage,
} from "@waku/interfaces";
import type { HookState } from "./types";
type AbstractStoreNode = {
store: IStore;
};
type UseStoreMessagesParams = {
node: AbstractStoreNode;
decoder: IDecoder<IDecodedMessage>;
options: StoreQueryOptions;
};
type UseStoreMessagesResult = HookState & {
messages: IDecodedMessage[];
};
const useStoreMessages = (
params: UseStoreMessagesParams,
): UseStoreMessagesResult => {
const { node, decoder, options } = params;
const [error, setError] = React.useState<undefined | string>(undefined);
const [isLoading, setLoading] = React.useState<boolean>(false);
const [messages, setMessage] = React.useState<IDecodedMessage[]>([]);
const pushMessage = React.useCallback(
(message: IDecodedMessage[]): void => {
setMessage((prev) => [...prev, ...message]);
},
[setMessage],
);
React.useEffect(() => {
let cancelled: boolean = false;
setLoading(true);
Promise
.resolve()
.then(async () => {
for await (const promises of node.store.queryGenerator([decoder], options)) {
if (cancelled) {
return;
}
const messagesRaw = await Promise.all(promises);
const filteredMessages = messagesRaw.filter((v): v is IDecodedMessage => !!v);
pushMessage(filteredMessages);
}
setLoading(false);
})
.catch((err) => {
setLoading(false);
setError(
`Failed to query messages from store: ${err?.message || "no message"}`,
);
});
return () => {
cancelled = true;
};
}, [node, decoder, options, pushMessage, setError, setLoading]);
return {
error,
isLoading,
messages,
};
};