From 695809117b00b867324e61b5031476d5f3532a80 Mon Sep 17 00:00:00 2001 From: SudheerCnEL Date: Thu, 16 Apr 2026 00:41:00 +0530 Subject: [PATCH 1/2] perf(button): memoize icon, label and badge rendering Optimize Button component by memoizing icon, label and badge computations using React.useMemo. - Prevents unnecessary recalculations on re-renders - Improves performance in high-frequency render scenarios - Inlined helper logic to avoid hook dependency issues - Maintains full backward compatibility" --- components/lib/button/Button.js | 77 +++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/components/lib/button/Button.js b/components/lib/button/Button.js index 01aeae0e08..4aa6dbfc7f 100644 --- a/components/lib/button/Button.js +++ b/components/lib/button/Button.js @@ -34,11 +34,7 @@ export const Button = React.memo( ObjectUtils.combinedRefs(elementRef, ref); }, [elementRef, ref]); - if (props.visible === false) { - return null; - } - - const createIcon = () => { + const icon = React.useMemo(() => { let className = classNames('p-button-icon p-c', { [`p-button-icon-${props.iconPos}`]: props.label }); @@ -61,12 +57,21 @@ export const Button = React.memo( ptm('loadingIcon') ); - const icon = props.loading ? props.loadingIcon || : props.icon; - - return IconUtils.getJSXIcon(icon, { ...iconsProps }, { props }); - }; - - const createLabel = () => { + const iconValue = props.loading ? props.loadingIcon || : props.icon; + + return IconUtils.getJSXIcon(iconValue, { ...iconsProps }, { props }); + }, [ + props.icon, + props.loading, + props.iconPos, + props.loadingIcon, + props.label, + mergeProps, + ptm, + cx + ]); + + const label = React.useMemo(() => { const labelProps = mergeProps( { className: cx('label') @@ -78,10 +83,18 @@ export const Button = React.memo( return {props.label}; } - return !props.children && !props.label && ; - }; - - const createBadge = () => { + return !props.children && !props.label && ( + + ); + }, [ + props.label, + props.children, + mergeProps, + ptm, + cx + ]); + + const badge = React.useMemo(() => { if (props.badge) { const badgeProps = mergeProps( { @@ -97,20 +110,33 @@ export const Button = React.memo( } return null; - }; + }, [ + props.badge, + props.badgeClassName, + props.unstyled, + mergeProps, + ptm, + metaData + ]); + + // ✅ AFTER hooks (important) + if (props.visible === false) { + return null; + } const showTooltip = !disabled || (props.tooltipOptions && props.tooltipOptions.showOnDisabled); const hasTooltip = ObjectUtils.isNotEmpty(props.tooltip) && showTooltip; + const sizeMapping = { large: 'lg', small: 'sm' }; + const size = sizeMapping[props.size]; - const icon = createIcon(); - const label = createLabel(); - const badge = createBadge(); - const defaultAriaLabel = props.label ? props.label + (props.badge ? ' ' + props.badge : '') : props['aria-label']; + const defaultAriaLabel = props.label + ? props.label + (props.badge ? ' ' + props.badge : '') + : props['aria-label']; const rootProps = mergeProps( { @@ -133,10 +159,17 @@ export const Button = React.memo( {badge} - {hasTooltip && } + {hasTooltip && ( + + )} ); }) ); -Button.displayName = 'Button'; +Button.displayName = 'Button'; \ No newline at end of file From 010349b3a6bddb1d9c0844657f407f7991a4561b Mon Sep 17 00:00:00 2001 From: SudheerCnEL Date: Thu, 16 Apr 2026 00:55:00 +0530 Subject: [PATCH 2/2] style(button): fix prettier formatting --- components/lib/button/Button.js | 47 +++++---------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) diff --git a/components/lib/button/Button.js b/components/lib/button/Button.js index 4aa6dbfc7f..1cf5eb13a6 100644 --- a/components/lib/button/Button.js +++ b/components/lib/button/Button.js @@ -60,16 +60,7 @@ export const Button = React.memo( const iconValue = props.loading ? props.loadingIcon || : props.icon; return IconUtils.getJSXIcon(iconValue, { ...iconsProps }, { props }); - }, [ - props.icon, - props.loading, - props.iconPos, - props.loadingIcon, - props.label, - mergeProps, - ptm, - cx - ]); + }, [props.icon, props.loading, props.iconPos, props.loadingIcon, props.label, mergeProps, ptm, cx]); const label = React.useMemo(() => { const labelProps = mergeProps( @@ -83,16 +74,8 @@ export const Button = React.memo( return {props.label}; } - return !props.children && !props.label && ( - - ); - }, [ - props.label, - props.children, - mergeProps, - ptm, - cx - ]); + return !props.children && !props.label && ; + }, [props.label, props.children, mergeProps, ptm, cx]); const badge = React.useMemo(() => { if (props.badge) { @@ -110,14 +93,7 @@ export const Button = React.memo( } return null; - }, [ - props.badge, - props.badgeClassName, - props.unstyled, - mergeProps, - ptm, - metaData - ]); + }, [props.badge, props.badgeClassName, props.unstyled, mergeProps, ptm, metaData]); // ✅ AFTER hooks (important) if (props.visible === false) { @@ -134,9 +110,7 @@ export const Button = React.memo( const size = sizeMapping[props.size]; - const defaultAriaLabel = props.label - ? props.label + (props.badge ? ' ' + props.badge : '') - : props['aria-label']; + const defaultAriaLabel = props.label ? props.label + (props.badge ? ' ' + props.badge : '') : props['aria-label']; const rootProps = mergeProps( { @@ -159,17 +133,10 @@ export const Button = React.memo( {badge} - {hasTooltip && ( - - )} + {hasTooltip && } ); }) ); -Button.displayName = 'Button'; \ No newline at end of file +Button.displayName = 'Button';