perf(components): prevent rerenders from updatingState

Use Zustand selectors with custom equality functions to only subscribe to specific fields needed by components, avoiding unnecessary rerenders when transient state like updatingState changes. Extract offline indicators into separate components to isolate rerenders. Memoize card components in catalog and popular threads views.
This commit is contained in:
plebeius
2026-01-02 16:42:16 +01:00
parent 764b4258e6
commit fa32833b2a
15 changed files with 446 additions and 322 deletions
+15 -8
View File
@@ -14,6 +14,19 @@ import { useResolvedSubplebbitAddress } from '../../hooks/use-resolved-subplebbi
import useFetchGifFirstFrame from '../../hooks/use-fetch-gif-first-frame';
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
import usePublishPost from '../../hooks/use-publish-post';
// Separate component for offline alert to isolate rerenders from updatingState
// Only this component will rerender when updatingState changes, not the whole PostForm
const OfflineAlert = ({ subplebbitAddress }: { subplebbitAddress: string | undefined }) => {
const subplebbit = useSubplebbitsStore((state) => (subplebbitAddress ? state.subplebbits[subplebbitAddress] : undefined));
const { isOffline, isOnlineStatusLoading, offlineTitle } = useIsSubplebbitOffline(subplebbit);
if (!isOffline && !isOnlineStatusLoading) {
return null;
}
return <div className={styles.offlineBoard}>{offlineTitle}</div>;
};
import usePublishReply from '../../hooks/use-publish-reply';
import FileUploader from '../../plugins/file-uploader';
import styles from './post-form.module.css';
@@ -380,15 +393,11 @@ const PostForm = () => {
const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any });
const resolvedAddress = useResolvedSubplebbitAddress();
const subplebbitAddress = resolvedAddress || accountComment?.subplebbitAddress;
const subplebbit = useSubplebbitsStore((state) => state.subplebbits[subplebbitAddress]);
const { isOffline, isOnlineStatusLoading, offlineTitle } = useIsSubplebbitOffline(subplebbit);
return (
<>
<div className={styles.postFormDesktop}>
{!(isInAllView || isInSubscriptionsView || isInModView) && showForm && (isOffline || isOnlineStatusLoading) && (
<div className={styles.offlineBoard}>{offlineTitle}</div>
)}
{!(isInAllView || isInSubscriptionsView || isInModView) && showForm && <OfflineAlert subplebbitAddress={subplebbitAddress} />}
{isThreadClosed ? (
<div className={styles.closed}>
{t('thread_closed')}
@@ -408,9 +417,7 @@ const PostForm = () => {
)}
</div>
<div className={styles.postFormMobile}>
{!(isInAllView || isInSubscriptionsView || isInModView) && showForm && (isOffline || isOnlineStatusLoading) && (
<div className={styles.offlineBoard}>{offlineTitle}</div>
)}
{!(isInAllView || isInSubscriptionsView || isInModView) && showForm && <OfflineAlert subplebbitAddress={subplebbitAddress} />}
{isThreadClosed ? (
<div className={styles.closed}>
{t('thread_closed')}