improve error handling for useevent hook

This commit is contained in:
2023-12-05 09:42:08 +07:00
parent e06b760e41
commit 482b218f74
6 changed files with 64 additions and 30 deletions

View File

@@ -4,6 +4,7 @@ import { nip19 } from 'nostr-tools';
import { EventPointer } from 'nostr-tools/lib/types/nip19'; import { EventPointer } from 'nostr-tools/lib/types/nip19';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { toast } from 'sonner';
import { ArrowLeftIcon, CheckCircleIcon, ShareIcon } from '@shared/icons'; import { ArrowLeftIcon, CheckCircleIcon, ShareIcon } from '@shared/icons';
import { NoteReplyForm } from '@shared/notes'; import { NoteReplyForm } from '@shared/notes';
@@ -40,14 +41,18 @@ export function ArticleNoteScreen() {
}, [data]); }, [data]);
const share = async () => { const share = async () => {
await writeText( try {
'https://njump.me/' + await writeText(
nip19.neventEncode({ id: data.id, author: data.pubkey } as EventPointer) 'https://njump.me/' +
); nip19.neventEncode({ id: data?.id, author: data?.pubkey } as EventPointer)
// update state );
setIsCopy(true); // update state
// reset state after 2 sec setIsCopy(true);
setTimeout(() => setIsCopy(false), 2000); // reset state after 2 sec
setTimeout(() => setIsCopy(false), 2000);
} catch (e) {
toast.error(e);
}
}; };
return ( return (

View File

@@ -4,6 +4,7 @@ import { nip19 } from 'nostr-tools';
import { EventPointer } from 'nostr-tools/lib/types/nip19'; import { EventPointer } from 'nostr-tools/lib/types/nip19';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { toast } from 'sonner';
import { ArrowLeftIcon, CheckCircleIcon, ReplyIcon, ShareIcon } from '@shared/icons'; import { ArrowLeftIcon, CheckCircleIcon, ReplyIcon, ShareIcon } from '@shared/icons';
import { import {
@@ -30,14 +31,18 @@ export function TextNoteScreen() {
const [isCopy, setIsCopy] = useState(false); const [isCopy, setIsCopy] = useState(false);
const share = async () => { const share = async () => {
await writeText( try {
'https://njump.me/' + await writeText(
nip19.neventEncode({ id: data.id, author: data.pubkey } as EventPointer) 'https://njump.me/' +
); nip19.neventEncode({ id: data?.id, author: data?.pubkey } as EventPointer)
// update state );
setIsCopy(true); // update state
// reset state after 2 sec setIsCopy(true);
setTimeout(() => setIsCopy(false), 2000); // reset state after 2 sec
setTimeout(() => setIsCopy(false), 2000);
} catch (e) {
toast.error(e);
}
}; };
const scrollToReply = () => { const scrollToReply = () => {

View File

@@ -4,12 +4,22 @@ import { User } from '@shared/user';
import { useEvent } from '@utils/hooks/useEvent'; import { useEvent } from '@utils/hooks/useEvent';
export function ChildNote({ id, isRoot }: { id: string; isRoot?: boolean }) { 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 <NoteSkeleton />; return <NoteSkeleton />;
} }
if (isError) {
return (
<div className="relative flex gap-3">
<div className="relative flex-1 rounded-md bg-neutral-200 px-2 py-2 dark:bg-neutral-800">
Failed to fetch event
</div>
</div>
);
}
return ( return (
<div className="relative flex gap-3"> <div className="relative flex gap-3">
<div className="relative flex-1 rounded-md bg-neutral-200 px-2 py-2 dark:bg-neutral-800"> <div className="relative flex-1 rounded-md bg-neutral-200 px-2 py-2 dark:bg-neutral-800">

View File

@@ -20,7 +20,7 @@ export const MentionNote = memo(function MentionNote({
id: string; id: string;
editing?: boolean; editing?: boolean;
}) { }) {
const { status, data } = useEvent(id); const { isFetching, isError, data } = useEvent(id);
const { addWidget } = useWidget(); const { addWidget } = useWidget();
const renderKind = (event: NDKEvent) => { const renderKind = (event: NDKEvent) => {
@@ -36,7 +36,7 @@ export const MentionNote = memo(function MentionNote({
} }
}; };
if (status === 'pending') { if (isFetching) {
return ( return (
<div className="w-full cursor-default rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900"> <div className="w-full cursor-default rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900">
<NoteSkeleton /> <NoteSkeleton />
@@ -44,6 +44,14 @@ export const MentionNote = memo(function MentionNote({
); );
} }
if (isError) {
return (
<div className="w-full cursor-default rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900">
Failed to fetch event
</div>
);
}
return ( return (
<div className="my-2 flex w-full cursor-default flex-col gap-1 rounded-lg bg-neutral-100 dark:bg-neutral-900"> <div className="my-2 flex w-full cursor-default flex-col gap-1 rounded-lg bg-neutral-100 dark:bg-neutral-900">
<div className="mt-3 px-3"> <div className="mt-3 px-3">

View File

@@ -21,7 +21,7 @@ import { useNostr } from '@utils/hooks/useNostr';
import { Widget } from '@utils/types'; import { Widget } from '@utils/types';
export function ThreadWidget({ widget }: { widget: Widget }) { export function ThreadWidget({ widget }: { widget: Widget }) {
const { status, data } = useEvent(widget.content); const { isFetching, isError, data } = useEvent(widget.content);
const { getEventThread } = useNostr(); const { getEventThread } = useNostr();
const renderKind = useCallback( const renderKind = useCallback(
@@ -59,16 +59,22 @@ export function ThreadWidget({ widget }: { widget: Widget }) {
<WidgetWrapper> <WidgetWrapper>
<TitleBar id={widget.id} title={widget.title} /> <TitleBar id={widget.id} title={widget.title} />
<WVList className="flex-1 overflow-y-auto px-3 pb-5"> <WVList className="flex-1 overflow-y-auto px-3 pb-5">
{status === 'pending' ? ( {isFetching ? (
<div className="flex h-16 items-center justify-center rounded-xl bg-neutral-50 px-3 py-3 dark:bg-neutral-950"> <div className="flex h-16 items-center justify-center rounded-xl bg-neutral-50 px-3 py-3 dark:bg-neutral-950">
<LoaderIcon className="h-5 w-5 animate-spin" /> <LoaderIcon className="h-5 w-5 animate-spin" />
</div> </div>
) : ( ) : (
<> <>
<div className="flex flex-col rounded-xl bg-neutral-50 dark:bg-neutral-950"> <div className="flex flex-col rounded-xl bg-neutral-50 dark:bg-neutral-950">
<User pubkey={data.pubkey} time={data.created_at} variant="thread" /> {isError ? (
{renderKind(data)} <div>Failed to fetch event</div>
<NoteActions event={data} /> ) : (
<>
<User pubkey={data.pubkey} time={data.created_at} variant="thread" />
{renderKind(data)}
<NoteActions event={data} />
</>
)}
</div> </div>
<NoteReplyForm rootEvent={data} /> <NoteReplyForm rootEvent={data} />
<ReplyList eventId={data.id} /> <ReplyList eventId={data.id} />

View File

@@ -7,7 +7,7 @@ import { useNDK } from '@libs/ndk/provider';
export function useEvent(id: undefined | string, embed?: undefined | string) { export function useEvent(id: undefined | string, embed?: undefined | string) {
const { ndk } = useNDK(); const { ndk } = useNDK();
const { status, data } = useQuery({ const { status, isFetching, isError, data } = useQuery({
queryKey: ['event', id], queryKey: ['event', id],
queryFn: async () => { queryFn: async () => {
const naddr = id.startsWith('naddr') const naddr = id.startsWith('naddr')
@@ -24,7 +24,7 @@ export function useEvent(id: undefined | string, embed?: undefined | string) {
const rEvent = [...rEvents].slice(-1)[0]; 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; return rEvent;
} }
@@ -37,14 +37,14 @@ export function useEvent(id: undefined | string, embed?: undefined | string) {
// get event from relay // get event from relay
const event = await ndk.fetchEvent(id); 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; return event;
}, },
staleTime: Infinity,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
refetchOnMount: false, refetchOnMount: false,
refetchOnReconnect: false, refetchOnReconnect: false,
staleTime: Infinity,
}); });
return { status, data }; return { status, isFetching, isError, data };
} }