waku-react/src/useStoreMessages.ts

94 lines
2.0 KiB
TypeScript
Raw Normal View History

2023-02-21 23:42:08 +01:00
import React from "react";
import type {
IDecodedMessage,
2023-02-21 23:43:57 +01:00
IDecoder,
IStore,
StoreQueryOptions,
Waku,
2023-02-21 23:42:08 +01:00
} from "@waku/interfaces";
2023-02-21 23:43:57 +01:00
2023-02-21 23:42:08 +01:00
import type { HookState } from "./types";
2023-02-23 00:41:45 +01:00
type AbstractStoreNode = Waku & {
2023-02-21 23:42:08 +01:00
store: IStore;
};
type UseStoreMessagesParams = {
node: undefined | AbstractStoreNode;
2023-02-21 23:42:08 +01:00
decoder: IDecoder<IDecodedMessage>;
options: StoreQueryOptions;
};
type UseStoreMessagesResult = HookState & {
messages: IDecodedMessage[];
};
2023-02-21 23:44:43 +01:00
export const useStoreMessages = (
2023-02-21 23:42:08 +01:00
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(
2023-02-23 00:41:45 +01:00
(messages: IDecodedMessage[]): void => {
if (!messages || !messages.length) {
return;
}
setMessage((prev) => [...prev, ...messages]);
2023-02-21 23:42:08 +01:00
},
[setMessage],
);
React.useEffect(() => {
if (!node) {
return;
}
2023-02-21 23:43:57 +01:00
let cancelled = false;
2023-02-21 23:42:08 +01:00
setLoading(true);
2023-02-21 23:43:57 +01:00
Promise.resolve()
.then(async () => {
for await (const promises of node.store.queryGenerator(
[decoder],
options,
)) {
if (cancelled) {
return;
}
2023-02-21 23:42:08 +01:00
2023-02-21 23:43:57 +01:00
const messagesRaw = await Promise.all(promises);
const filteredMessages = messagesRaw.filter(
(v): v is IDecodedMessage => !!v,
);
2023-02-21 23:42:08 +01:00
2023-02-21 23:43:57 +01:00
pushMessage(filteredMessages);
}
2023-02-21 23:42:08 +01:00
2023-02-21 23:43:57 +01:00
setLoading(false);
})
2023-02-21 23:42:08 +01:00
.catch((err) => {
setLoading(false);
setError(
2023-02-21 23:43:57 +01:00
`Failed to query messages from store: ${
err?.message || "no message"
}`,
2023-02-21 23:42:08 +01:00
);
});
return () => {
cancelled = true;
};
}, [node, decoder, options, pushMessage, setError, setLoading]);
return {
error,
isLoading,
messages,
};
};