perf(components): memoize post menus with minimal props

This commit is contained in:
plebeius
2025-12-05 17:38:17 +01:00
parent 5eceba0134
commit 698df59f19
6 changed files with 79 additions and 38 deletions
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { memo, useState } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { Comment, useBlock } from '@plebbit/plebbit-react-hooks';
@@ -13,16 +13,14 @@ import useHide from '../../../hooks/use-hide';
import EditMenu from '../../edit-menu/edit-menu';
import { isBoardView, isPostPageView } from '../../../lib/utils/view-utils';
import { useLocation, useParams } from 'react-router-dom';
import { PostMenuProps } from '../../../lib/utils/post-menu-props';
interface PostMenuMobileProps {
cid: string;
isDescription?: boolean;
type HideButtonProps = {
cid?: string;
isReply?: boolean;
isRules?: boolean;
postCid?: string;
subplebbitAddress?: string;
onClose?: () => void;
}
};
const CopyLinkButton = ({ cid, subplebbitAddress, linkType, onClose }: { cid?: string; subplebbitAddress: string; linkType: ShareLinkType; onClose: () => void }) => {
const { t } = useTranslation();
@@ -57,7 +55,7 @@ const ImageSearchButtons = ({ url, onClose }: { url: string; onClose: () => void
);
};
const HidePostButton = ({ cid, isReply, onClose, postCid }: PostMenuMobileProps) => {
const HidePostButton = ({ cid, isReply, onClose, postCid }: HideButtonProps) => {
const { t } = useTranslation();
const { hide, hidden, unhide } = useHide({ cid });
const isInPostView = isPostPageView(useLocation().pathname, useParams());
@@ -98,9 +96,15 @@ const BlockBoardButton = ({ address }: { address: string }) => {
);
};
const PostMenuMobile = ({ post }: { post: Comment }) => {
const { author, cid, deleted, isDescription, isRules, link, linkHeight, linkWidth, parentCid, postCid, removed, subplebbitAddress, thumbnailUrl } = post || {};
const { isAccountMod, isAccountCommentAuthor } = useEditCommentPrivileges({ commentAuthorAddress: author?.address, subplebbitAddress });
type PostMenuMobileProps = {
postMenu: PostMenuProps;
editMenuPost: Comment;
};
const PostMenuMobile = ({ postMenu, editMenuPost }: PostMenuMobileProps) => {
const { authorAddress, cid, deleted, isDescription, isRules, link, linkHeight, linkWidth, parentCid, postCid, removed, subplebbitAddress, thumbnailUrl } =
postMenu || {};
const { isAccountMod, isAccountCommentAuthor } = useEditCommentPrivileges({ commentAuthorAddress: authorAddress, subplebbitAddress });
const commentMediaInfo = getCommentMediaInfo(link, thumbnailUrl, linkWidth, linkHeight);
const { thumbnail, type, url } = commentMediaInfo || {};
const [isMenuOpen, setIsMenuOpen] = useState(false);
@@ -142,8 +146,8 @@ const PostMenuMobile = ({ post }: { post: Comment }) => {
{cid && subplebbitAddress && <CopyLinkButton cid={cid} subplebbitAddress={subplebbitAddress} linkType='thread' onClose={handleClose} />}
{!cid && isDescription && subplebbitAddress && <CopyLinkButton subplebbitAddress={subplebbitAddress} linkType='description' onClose={handleClose} />}
{!cid && isRules && subplebbitAddress && <CopyLinkButton subplebbitAddress={subplebbitAddress} linkType='rules' onClose={handleClose} />}
{cid && subplebbitAddress && <HidePostButton cid={cid} isReply={parentCid} postCid={postCid} onClose={handleClose} />}
{cid && subplebbitAddress && !isDescription && !isRules && <BlockUserButton address={author?.address} />}
{cid && subplebbitAddress && <HidePostButton cid={cid} isReply={!!parentCid} postCid={postCid} onClose={handleClose} />}
{cid && subplebbitAddress && !isDescription && !isRules && authorAddress && <BlockUserButton address={authorAddress} />}
{cid && subplebbitAddress && !isInBoardView && !isDescription && !isRules && <BlockBoardButton address={subplebbitAddress} />}
{link && isValidURL(link) && (type === 'image' || type === 'gif' || thumbnail) && url && <ImageSearchButtons url={url} onClose={handleClose} />}
</div>
@@ -154,11 +158,11 @@ const PostMenuMobile = ({ post }: { post: Comment }) => {
)}
{(isAccountMod || isAccountCommentAuthor) && cid && (
<span className={styles.checkbox}>
<EditMenu post={post} />
<EditMenu post={editMenuPost} />
</span>
)}
</>
);
};
export default PostMenuMobile;
export default memo(PostMenuMobile);
+4 -2
View File
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Link, useLocation, useParams } from 'react-router-dom';
import { Comment, useAuthorAvatar, useEditedComment } from '@plebbit/plebbit-react-hooks';
@@ -28,6 +28,7 @@ import Tooltip from '../tooltip';
import { PostProps } from '../../views/post/post';
import _ from 'lodash';
import useReplyModalStore from '../../stores/use-reply-modal-store';
import { selectPostMenuProps } from '../../lib/utils/post-menu-props';
const PostInfoAndMedia = ({ post, postReplyCount = 0, roles }: PostProps) => {
const { t } = useTranslation();
@@ -71,6 +72,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles }: PostProps) => {
const hasThumbnail = getHasThumbnail(commentMediaInfo, link);
const stateString = useStateString(post);
const postMenuProps = useMemo(() => selectPostMenuProps(post), [post]);
const handleUserAddressClick = useAuthorAddressClick();
const numberOfPostsByAuthor = document.querySelectorAll(`[data-author-address="${shortAddress}"][data-post-cid="${postCid}"]`).length;
@@ -98,7 +100,7 @@ const PostInfoAndMedia = ({ post, postReplyCount = 0, roles }: PostProps) => {
return (
<>
<div className={styles.postInfo}>
<PostMenuMobile post={post} />
<PostMenuMobile postMenu={postMenuProps} editMenuPost={post} />
<span className={(hidden || ((removed || deleted) && !reason)) && parentCid ? styles.postDesktopHidden : ''}>
<span className={styles.nameBlock}>
<span className={`${styles.name} ${authorRole && !(deleted || removed) && (authorRole === 'mod' ? styles.capcodeMod : styles.capcodeAdmin)}`}>