From 2f963748377c267483f23bb8ee2f365ee747d652 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Mon, 8 Dec 2025 14:09:03 +0800 Subject: [PATCH] perf: optimize marketplace card re-renders with memoization (#29263) --- .../plugins/card/base/download-count.tsx | 6 ++++- .../plugins/card/card-more-info.tsx | 6 ++++- .../plugins/marketplace/list/card-wrapper.tsx | 26 +++++++++++++++---- web/app/components/plugins/provider-card.tsx | 14 +++++++--- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/web/app/components/plugins/card/base/download-count.tsx b/web/app/components/plugins/card/base/download-count.tsx index 7b3ae4de28..016a976777 100644 --- a/web/app/components/plugins/card/base/download-count.tsx +++ b/web/app/components/plugins/card/base/download-count.tsx @@ -1,3 +1,4 @@ +import React from 'react' import { RiInstallLine } from '@remixicon/react' import { formatNumber } from '@/utils/format' @@ -5,7 +6,7 @@ type Props = { downloadCount: number } -const DownloadCount = ({ +const DownloadCountComponent = ({ downloadCount, }: Props) => { return ( @@ -16,4 +17,7 @@ const DownloadCount = ({ ) } +// Memoize to prevent unnecessary re-renders +const DownloadCount = React.memo(DownloadCountComponent) + export default DownloadCount diff --git a/web/app/components/plugins/card/card-more-info.tsx b/web/app/components/plugins/card/card-more-info.tsx index 48533615ab..d81c941e96 100644 --- a/web/app/components/plugins/card/card-more-info.tsx +++ b/web/app/components/plugins/card/card-more-info.tsx @@ -1,3 +1,4 @@ +import React from 'react' import DownloadCount from './base/download-count' type Props = { @@ -5,7 +6,7 @@ type Props = { tags: string[] } -const CardMoreInfo = ({ +const CardMoreInfoComponent = ({ downloadCount, tags, }: Props) => { @@ -33,4 +34,7 @@ const CardMoreInfo = ({ ) } +// Memoize to prevent unnecessary re-renders when tags array hasn't changed +const CardMoreInfo = React.memo(CardMoreInfoComponent) + export default CardMoreInfo diff --git a/web/app/components/plugins/marketplace/list/card-wrapper.tsx b/web/app/components/plugins/marketplace/list/card-wrapper.tsx index d2a38b3ce3..785718e697 100644 --- a/web/app/components/plugins/marketplace/list/card-wrapper.tsx +++ b/web/app/components/plugins/marketplace/list/card-wrapper.tsx @@ -1,4 +1,5 @@ 'use client' +import React, { useMemo } from 'react' import { useTheme } from 'next-themes' import { RiArrowRightUpLine } from '@remixicon/react' import { getPluginDetailLinkInMarketplace, getPluginLinkInMarketplace } from '../utils' @@ -17,7 +18,7 @@ type CardWrapperProps = { showInstallButton?: boolean locale?: string } -const CardWrapper = ({ +const CardWrapperComponent = ({ plugin, showInstallButton, locale, @@ -31,6 +32,18 @@ const CardWrapper = ({ const { locale: localeFromLocale } = useI18N() const { getTagLabel } = useTags(t) + // Memoize marketplace link params to prevent unnecessary re-renders + const marketplaceLinkParams = useMemo(() => ({ + language: localeFromLocale, + theme, + }), [localeFromLocale, theme]) + + // Memoize tag labels to prevent recreating array on every render + const tagLabels = useMemo(() => + plugin.tags.map(tag => getTagLabel(tag.name)), + [plugin.tags, getTagLabel], + ) + if (showInstallButton) { return (