fix(views): display useSubplebbit and useComment errors in board, post, and mod-queue views

This commit is contained in:
plebeius
2026-01-12 17:59:03 +01:00
parent 1459363024
commit 122b17790a
4 changed files with 46 additions and 11 deletions
+4 -4
View File
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useRef, useState } from 'react'; import { useEffect, useMemo, useRef, useState } from 'react';
import { Link, useLocation, useNavigationType, useParams } from 'react-router-dom'; import { Link, useLocation, useNavigationType, useParams } from 'react-router-dom';
import { Comment, useAccount, useAccountComments, useAccountSubplebbits, useBlock, useFeed } from '@plebbit/plebbit-react-hooks'; import { Comment, useAccount, useAccountComments, useAccountSubplebbits, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import { useSubplebbitField } from '../../hooks/use-stable-subplebbit'; import { useSubplebbitField } from '../../hooks/use-stable-subplebbit';
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso'; import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { Trans, useTranslation } from 'react-i18next'; import { Trans, useTranslation } from 'react-i18next';
@@ -157,9 +157,9 @@ const Board = ({ feedCacheKey, viewType, boardIdentifier: boardIdentifierProp, t
// Use stable subplebbit fields to avoid rerenders from updatingState // Use stable subplebbit fields to avoid rerenders from updatingState
const subplebbitTitle = useSubplebbitField(subplebbitAddress, (sub) => sub?.title); const subplebbitTitle = useSubplebbitField(subplebbitAddress, (sub) => sub?.title);
const shortAddress = useSubplebbitField(subplebbitAddress, (sub) => sub?.shortAddress); const shortAddress = useSubplebbitField(subplebbitAddress, (sub) => sub?.shortAddress);
// Subscribe to transient state/error separately from stable fields since useStableSubplebbit ignores them // useSubplebbitField only reads from store, doesn't trigger fetching
const subplebbitState = useSubplebbitField(subplebbitAddress, (sub) => sub?.state); const subplebbit = useSubplebbit({ subplebbitAddress });
const subplebbitError = useSubplebbitField(subplebbitAddress, (sub) => sub?.error); const { error: subplebbitError, state: subplebbitState } = subplebbit || {};
const title = isInAllView ? t('all') : isInSubscriptionsView ? t('subscriptions') : isInModView ? t('mod') : subplebbitTitle; const title = isInAllView ? t('all') : isInSubscriptionsView ? t('subscriptions') : isInModView ? t('mod') : subplebbitTitle;
const { blocked, unblock } = useBlock({ address: subplebbitAddress }); const { blocked, unblock } = useBlock({ address: subplebbitAddress });
+5
View File
@@ -105,6 +105,11 @@
justify-content: center; justify-content: center;
} }
.error {
padding: 10px;
text-align: center;
}
/* ModQueueRow styles */ /* ModQueueRow styles */
.row { .row {
display: flex; display: flex;
+22 -3
View File
@@ -1,7 +1,7 @@
import React, { useMemo, useState, useEffect } from 'react'; import React, { useMemo, useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useParams, Link } from 'react-router-dom'; import { useParams, Link } from 'react-router-dom';
import { useFeed, Comment, usePublishCommentModeration, useEditedComment } from '@plebbit/plebbit-react-hooks'; import { useFeed, Comment, usePublishCommentModeration, useEditedComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import useAccountsStore from '@plebbit/plebbit-react-hooks/dist/stores/accounts'; import useAccountsStore from '@plebbit/plebbit-react-hooks/dist/stores/accounts';
import { Virtuoso } from 'react-virtuoso'; import { Virtuoso } from 'react-virtuoso';
import { formatDistanceToNow } from 'date-fns'; import { formatDistanceToNow } from 'date-fns';
@@ -9,6 +9,7 @@ import styles from './mod-queue.module.css';
import useModQueueStore from '../../stores/use-mod-queue-store'; import useModQueueStore from '../../stores/use-mod-queue-store';
import { useAccountSubplebbitsWithMetadata } from '../../hooks/use-account-subplebbits-with-metadata'; import { useAccountSubplebbitsWithMetadata } from '../../hooks/use-account-subplebbits-with-metadata';
import LoadingEllipsis from '../../components/loading-ellipsis'; import LoadingEllipsis from '../../components/loading-ellipsis';
import ErrorDisplay from '../../components/error-display/error-display';
import { useFeedStateString } from '../../hooks/use-state-string'; import { useFeedStateString } from '../../hooks/use-state-string';
import { getSubplebbitAddress, getBoardPath } from '../../lib/utils/route-utils'; import { getSubplebbitAddress, getBoardPath } from '../../lib/utils/route-utils';
import { useDefaultSubplebbits, MultisubSubplebbit } from '../../hooks/use-default-subplebbits'; import { useDefaultSubplebbits, MultisubSubplebbit } from '../../hooks/use-default-subplebbits';
@@ -489,6 +490,10 @@ export const ModQueueView = ({ boardIdentifier: propBoardIdentifier }: ModQueueV
return []; return [];
}, [resolvedAddress, selectedBoardFilter, accountSubplebbitAddresses]); }, [resolvedAddress, selectedBoardFilter, accountSubplebbitAddresses]);
const subplebbitAddress = subplebbitAddresses[0];
const subplebbit = useSubplebbit({ subplebbitAddress });
const { error: subplebbitError } = subplebbit || {};
const { feed, hasMore, loadMore, reset } = useFeed({ const { feed, hasMore, loadMore, reset } = useFeed({
subplebbitAddresses, subplebbitAddresses,
modQueue: ['pendingApproval'], modQueue: ['pendingApproval'],
@@ -513,9 +518,18 @@ export const ModQueueView = ({ boardIdentifier: propBoardIdentifier }: ModQueueV
// Note: useFeedStateString is called inside ModQueueFooter to isolate re-renders from backend state changes // Note: useFeedStateString is called inside ModQueueFooter to isolate re-renders from backend state changes
const footerComponents = useMemo( const footerComponents = useMemo(
() => ({ () => ({
Footer: () => <ModQueueFooter hasMore={hasMore} subplebbitAddresses={subplebbitAddresses} />, Footer: () => (
<>
{subplebbitError?.message && feed.length === 0 && (
<div className={styles.error}>
<ErrorDisplay error={subplebbitError} />
</div>
)}
<ModQueueFooter hasMore={hasMore} subplebbitAddresses={subplebbitAddresses} />
</>
),
}), }),
[hasMore, subplebbitAddresses], [hasMore, subplebbitAddresses, subplebbitError, feed.length],
); );
const alertThresholdControl = ( const alertThresholdControl = (
@@ -603,6 +617,11 @@ export const ModQueueView = ({ boardIdentifier: propBoardIdentifier }: ModQueueV
{feed.map((comment, index) => ( {feed.map((comment, index) => (
<ModQueueRow key={comment.cid} comment={comment} isOdd={index % 2 === 0} /> <ModQueueRow key={comment.cid} comment={comment} isOdd={index % 2 === 0} />
))} ))}
{subplebbitError?.message && feed.length === 0 && (
<div className={styles.error}>
<ErrorDisplay error={subplebbitError} />
</div>
)}
<ModQueueFooter hasMore={hasMore} subplebbitAddresses={subplebbitAddresses} /> <ModQueueFooter hasMore={hasMore} subplebbitAddresses={subplebbitAddresses} />
</> </>
)} )}
+15 -4
View File
@@ -70,7 +70,7 @@ const PostPage = () => {
}, [comment?.subplebbitAddress, subplebbitAddress, navigate]); }, [comment?.subplebbitAddress, subplebbitAddress, navigate]);
const subplebbit = useSubplebbit({ subplebbitAddress }); const subplebbit = useSubplebbit({ subplebbitAddress });
const { shortAddress, title } = subplebbit || {}; const { error: subplebbitError, shortAddress, title } = subplebbit || {};
const defaultSubplebbits = useDefaultSubplebbits(); const defaultSubplebbits = useDefaultSubplebbits();
// if the comment is a reply, return the post comment instead, then the reply will be highlighted in the thread // if the comment is a reply, return the post comment instead, then the reply will be highlighted in the thread
@@ -106,17 +106,28 @@ const PostPage = () => {
document.title = `${boardTitle}${postTitlePart} - 5chan`; document.title = `${boardTitle}${postTitlePart} - 5chan`;
}, [title, shortAddress, subplebbitAddress, post?.title, post?.content, isInAllView, t, params.boardIdentifier, defaultSubplebbits]); }, [title, shortAddress, subplebbitAddress, post?.title, post?.content, isInAllView, t, params.boardIdentifier, defaultSubplebbits]);
// probably not necessary to show the error to the user if the post loaded successfully const shouldShowCommentError = comment?.error?.message && !comment?.cid;
const shouldShowErrorToUser = post?.error && ((post?.replyCount > 0 && post?.replies?.length === 0) || (post?.state === 'failed' && post?.error)); const shouldShowPostError = post?.error && post?.replyCount > 0 && post?.replies?.length === 0;
const shouldShowSubplebbitError = subplebbitError?.message && !post?.cid;
return ( return (
<div className={styles.content}> <div className={styles.content}>
{shouldShowErrorToUser && ( {shouldShowPostError && (
<div className={styles.error}> <div className={styles.error}>
<ErrorDisplay error={error} /> <ErrorDisplay error={error} />
</div> </div>
)} )}
<Post post={post} showAllReplies={true} /> <Post post={post} showAllReplies={true} />
{shouldShowSubplebbitError && (
<div className={styles.error}>
<ErrorDisplay error={subplebbitError} />
</div>
)}
{shouldShowCommentError && (
<div className={styles.error}>
<ErrorDisplay error={comment?.error} />
</div>
)}
</div> </div>
); );
}; };