From 482b218f74feb0f568298eb0adf8cf93d7912d9b Mon Sep 17 00:00:00 2001 From: reya Date: Tue, 5 Dec 2023 09:42:08 +0700 Subject: [PATCH] improve error handling for useevent hook --- src/app/notes/article.tsx | 21 +++++++++++++-------- src/app/notes/text.tsx | 21 +++++++++++++-------- src/shared/notes/child.tsx | 14 ++++++++++++-- src/shared/notes/mentions/note.tsx | 12 ++++++++++-- src/shared/widgets/thread.tsx | 16 +++++++++++----- src/utils/hooks/useEvent.ts | 10 +++++----- 6 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/app/notes/article.tsx b/src/app/notes/article.tsx index d4a1ba2b..912489db 100644 --- a/src/app/notes/article.tsx +++ b/src/app/notes/article.tsx @@ -4,6 +4,7 @@ import { nip19 } from 'nostr-tools'; import { EventPointer } from 'nostr-tools/lib/types/nip19'; import { useMemo, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; +import { toast } from 'sonner'; import { ArrowLeftIcon, CheckCircleIcon, ShareIcon } from '@shared/icons'; import { NoteReplyForm } from '@shared/notes'; @@ -40,14 +41,18 @@ export function ArticleNoteScreen() { }, [data]); const share = async () => { - await writeText( - 'https://njump.me/' + - nip19.neventEncode({ id: data.id, author: data.pubkey } as EventPointer) - ); - // update state - setIsCopy(true); - // reset state after 2 sec - setTimeout(() => setIsCopy(false), 2000); + try { + await writeText( + 'https://njump.me/' + + nip19.neventEncode({ id: data?.id, author: data?.pubkey } as EventPointer) + ); + // update state + setIsCopy(true); + // reset state after 2 sec + setTimeout(() => setIsCopy(false), 2000); + } catch (e) { + toast.error(e); + } }; return ( diff --git a/src/app/notes/text.tsx b/src/app/notes/text.tsx index 7228489f..9e723251 100644 --- a/src/app/notes/text.tsx +++ b/src/app/notes/text.tsx @@ -4,6 +4,7 @@ import { nip19 } from 'nostr-tools'; import { EventPointer } from 'nostr-tools/lib/types/nip19'; import { useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; +import { toast } from 'sonner'; import { ArrowLeftIcon, CheckCircleIcon, ReplyIcon, ShareIcon } from '@shared/icons'; import { @@ -30,14 +31,18 @@ export function TextNoteScreen() { const [isCopy, setIsCopy] = useState(false); const share = async () => { - await writeText( - 'https://njump.me/' + - nip19.neventEncode({ id: data.id, author: data.pubkey } as EventPointer) - ); - // update state - setIsCopy(true); - // reset state after 2 sec - setTimeout(() => setIsCopy(false), 2000); + try { + await writeText( + 'https://njump.me/' + + nip19.neventEncode({ id: data?.id, author: data?.pubkey } as EventPointer) + ); + // update state + setIsCopy(true); + // reset state after 2 sec + setTimeout(() => setIsCopy(false), 2000); + } catch (e) { + toast.error(e); + } }; const scrollToReply = () => { diff --git a/src/shared/notes/child.tsx b/src/shared/notes/child.tsx index 00f9ed15..40c79974 100644 --- a/src/shared/notes/child.tsx +++ b/src/shared/notes/child.tsx @@ -4,12 +4,22 @@ import { User } from '@shared/user'; import { useEvent } from '@utils/hooks/useEvent'; export function ChildNote({ id, isRoot }: { id: string; isRoot?: boolean }) { - const { status, data } = useEvent(id); + const { isFetching, isError, data } = useEvent(id); - if (status === 'pending' || !data) { + if (isFetching) { return ; } + if (isError) { + return ( +
+
+ Failed to fetch event +
+
+ ); + } + return (
diff --git a/src/shared/notes/mentions/note.tsx b/src/shared/notes/mentions/note.tsx index cce5a106..f97cea61 100644 --- a/src/shared/notes/mentions/note.tsx +++ b/src/shared/notes/mentions/note.tsx @@ -20,7 +20,7 @@ export const MentionNote = memo(function MentionNote({ id: string; editing?: boolean; }) { - const { status, data } = useEvent(id); + const { isFetching, isError, data } = useEvent(id); const { addWidget } = useWidget(); const renderKind = (event: NDKEvent) => { @@ -36,7 +36,7 @@ export const MentionNote = memo(function MentionNote({ } }; - if (status === 'pending') { + if (isFetching) { return (
@@ -44,6 +44,14 @@ export const MentionNote = memo(function MentionNote({ ); } + if (isError) { + return ( +
+ Failed to fetch event +
+ ); + } + return (
diff --git a/src/shared/widgets/thread.tsx b/src/shared/widgets/thread.tsx index 8e10d255..dcb70fe2 100644 --- a/src/shared/widgets/thread.tsx +++ b/src/shared/widgets/thread.tsx @@ -21,7 +21,7 @@ import { useNostr } from '@utils/hooks/useNostr'; import { Widget } from '@utils/types'; export function ThreadWidget({ widget }: { widget: Widget }) { - const { status, data } = useEvent(widget.content); + const { isFetching, isError, data } = useEvent(widget.content); const { getEventThread } = useNostr(); const renderKind = useCallback( @@ -59,16 +59,22 @@ export function ThreadWidget({ widget }: { widget: Widget }) { - {status === 'pending' ? ( + {isFetching ? (
) : ( <>
- - {renderKind(data)} - + {isError ? ( +
Failed to fetch event
+ ) : ( + <> + + {renderKind(data)} + + + )}
diff --git a/src/utils/hooks/useEvent.ts b/src/utils/hooks/useEvent.ts index 6082ff74..783eef55 100644 --- a/src/utils/hooks/useEvent.ts +++ b/src/utils/hooks/useEvent.ts @@ -7,7 +7,7 @@ import { useNDK } from '@libs/ndk/provider'; export function useEvent(id: undefined | string, embed?: undefined | string) { const { ndk } = useNDK(); - const { status, data } = useQuery({ + const { status, isFetching, isError, data } = useQuery({ queryKey: ['event', id], queryFn: async () => { const naddr = id.startsWith('naddr') @@ -24,7 +24,7 @@ export function useEvent(id: undefined | string, embed?: undefined | string) { const rEvent = [...rEvents].slice(-1)[0]; - if (!rEvent) return Promise.reject(new Error('event not found')); + if (!rEvent) throw new Error('event not found'); return rEvent; } @@ -37,14 +37,14 @@ export function useEvent(id: undefined | string, embed?: undefined | string) { // get event from relay const event = await ndk.fetchEvent(id); - if (!event) return Promise.reject(new Error('event not found')); + if (!event) throw new Error('event not found'); return event; }, + staleTime: Infinity, refetchOnWindowFocus: false, refetchOnMount: false, refetchOnReconnect: false, - staleTime: Infinity, }); - return { status, data }; + return { status, isFetching, isError, data }; }