improve error handling for useevent hook
This commit is contained in:
@@ -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 (
|
||||||
|
|||||||
@@ -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 = () => {
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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} />
|
||||||
|
|||||||
@@ -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 };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user