Remove the components prop in favor of the native children prop to prevent unnecessary re-renders which are breaking component animations

This commit is contained in:
Daniel Dudzic 2024-12-17 11:50:32 +01:00
parent 51613c3020
commit f32f30ef0a
No known key found for this signature in database
GPG key ID: 31B40D33E3465483
13 changed files with 271 additions and 371 deletions

View file

@ -1,8 +1,6 @@
import { Icon } from '@wordpress/components'; import { Icon } from '@wordpress/components';
import { chevronDown, chevronUp } from '@wordpress/icons'; import { chevronDown, chevronUp } from '@wordpress/icons';
import classNames from 'classnames'; import classNames from 'classnames';
import { useAccordionState } from '../../hooks/useAccordionState'; import { useAccordionState } from '../../hooks/useAccordionState';
// Provide defaults for all layout components so the generic version just works. // Provide defaults for all layout components so the generic version just works.
@ -24,6 +22,13 @@ const DefaultDescription = ( { children } ) => (
<div className="ppcp-r-accordion__description">{ children }</div> <div className="ppcp-r-accordion__description">{ children }</div>
); );
const AccordionContent = ( { isOpen, children } ) => {
if ( ! isOpen || ! children ) {
return null;
}
return <div className="ppcp-r-accordion__content">{ children }</div>;
};
const Accordion = ( { const Accordion = ( {
title, title,
id = '', id = '',
@ -65,9 +70,7 @@ const Accordion = ( {
) } ) }
</Header> </Header>
</button> </button>
{ isOpen && children && ( <AccordionContent isOpen={ isOpen }>{ children }</AccordionContent>
<div className="ppcp-r-accordion__content">{ children }</div>
) }
</div> </div>
); );
}; };

View file

@ -9,11 +9,7 @@ import {
} from './SettingsBlockElements'; } from './SettingsBlockElements';
const SettingsAccordion = ( { title, description, children, ...props } ) => ( const SettingsAccordion = ( { title, description, children, ...props } ) => (
<SettingsBlock <SettingsBlock { ...props } className="ppcp-r-settings-block__accordion">
{ ...props }
className="ppcp-r-settings-block__accordion"
components={ [
() => (
<Accordion <Accordion
title={ title } title={ title }
description={ description } description={ description }
@ -25,9 +21,7 @@ const SettingsAccordion = ( { title, description, children, ...props } ) => (
> >
{ children } { children }
</Accordion> </Accordion>
), </SettingsBlock>
] }
/>
); );
export default SettingsAccordion; export default SettingsAccordion;

View file

@ -3,12 +3,7 @@ import SettingsBlock from './SettingsBlock';
import { Header, Title, Action, Description } from './SettingsBlockElements'; import { Header, Title, Action, Description } from './SettingsBlockElements';
const ButtonSettingsBlock = ( { title, description, ...props } ) => ( const ButtonSettingsBlock = ( { title, description, ...props } ) => (
<SettingsBlock <SettingsBlock { ...props } className="ppcp-r-settings-block__button">
{ ...props }
className="ppcp-r-settings-block__button"
components={ [
() => (
<>
<Header> <Header>
<Title>{ title }</Title> <Title>{ title }</Title>
<Description>{ description }</Description> <Description>{ description }</Description>
@ -25,10 +20,7 @@ const ButtonSettingsBlock = ( { title, description, ...props } ) => (
{ props.actionProps.value } { props.actionProps.value }
</Button> </Button>
</Action> </Action>
</> </SettingsBlock>
),
] }
/>
); );
export default ButtonSettingsBlock; export default ButtonSettingsBlock;

View file

@ -11,30 +11,21 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
} }
return ( return (
<>
<span className="ppcp-r-feature-item__notes"> <span className="ppcp-r-feature-item__notes">
{ notes.map( ( note, index ) => ( { notes.map( ( note, index ) => (
<span key={ index }>{ note }</span> <span key={ index }>{ note }</span>
) ) } ) ) }
</span> </span>
</>
); );
}; };
return ( return (
<SettingsBlock <SettingsBlock { ...props } className="ppcp-r-settings-block__feature">
{ ...props }
className="ppcp-r-settings-block__feature"
components={ [
() => (
<>
<Header> <Header>
<Title> <Title>
{ title } { title }
{ props.actionProps?.featureStatus && ( { props.actionProps?.featureStatus && (
<TitleBadge <TitleBadge { ...props.actionProps?.badge } />
{ ...props.actionProps?.badge }
/>
) } ) }
</Title> </Title>
<Description className="ppcp-r-settings-block__feature__description"> <Description className="ppcp-r-settings-block__feature__description">
@ -44,8 +35,7 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
</Header> </Header>
<Action> <Action>
<div className="ppcp-r-feature-item__buttons"> <div className="ppcp-r-feature-item__buttons">
{ props.actionProps?.buttons.map( { props.actionProps?.buttons.map( ( button ) => (
( button ) => (
<Button <Button
href={ button.url } href={ button.url }
key={ button.text } key={ button.text }
@ -53,14 +43,10 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
> >
{ button.text } { button.text }
</Button> </Button>
) ) ) }
) }
</div> </div>
</Action> </Action>
</> </SettingsBlock>
),
] }
/>
); );
}; };

View file

@ -42,12 +42,7 @@ const InputSettingsBlock = ( {
order = DEFAULT_ELEMENT_ORDER, order = DEFAULT_ELEMENT_ORDER,
...props ...props
} ) => ( } ) => (
<SettingsBlock <SettingsBlock { ...props } className="ppcp-r-settings-block__input">
{ ...props }
className="ppcp-r-settings-block__input"
components={ [
() => (
<>
{ order.map( ( elementKey ) => { { order.map( ( elementKey ) => {
const RenderElement = ELEMENT_RENDERERS[ elementKey ]; const RenderElement = ELEMENT_RENDERERS[ elementKey ];
return RenderElement ? ( return RenderElement ? (
@ -60,10 +55,7 @@ const InputSettingsBlock = ( {
/> />
) : null; ) : null;
} ) } } ) }
</> </SettingsBlock>
),
] }
/>
); );
export default InputSettingsBlock; export default InputSettingsBlock;

View file

@ -16,25 +16,18 @@ const PaymentMethodsBlock = ( { paymentMethods, className = '' } ) => {
return ( return (
<SettingsBlock <SettingsBlock
className={ `ppcp-r-settings-block__payment-methods ${ className }` } className={ `ppcp-r-settings-block__payment-methods ${ className }` }
components={ [ >
() => (
<>
{ paymentMethods.map( ( paymentMethod ) => ( { paymentMethods.map( ( paymentMethod ) => (
<PaymentMethodItemBlock <PaymentMethodItemBlock
key={ paymentMethod.id } key={ paymentMethod.id }
{ ...paymentMethod } { ...paymentMethod }
isSelected={ isSelected={ selectedMethod === paymentMethod.id }
selectedMethod === paymentMethod.id
}
onSelect={ ( checked ) => onSelect={ ( checked ) =>
handleSelect( paymentMethod.id, checked ) handleSelect( paymentMethod.id, checked )
} }
/> />
) ) } ) ) }
</> </SettingsBlock>
),
] }
/>
); );
}; };

View file

@ -11,9 +11,7 @@ const RadioSettingsBlock = ( {
<SettingsBlock <SettingsBlock
{ ...props } { ...props }
className="ppcp-r-settings-block__radio ppcp-r-settings-block--expert-rdb" className="ppcp-r-settings-block__radio ppcp-r-settings-block--expert-rdb"
components={ [ >
() => (
<>
<Header> <Header>
<Title>{ title }</Title> <Title>{ title }</Title>
<Description>{ description }</Description> <Description>{ description }</Description>
@ -38,10 +36,7 @@ const RadioSettingsBlock = ( {
{ option.additionalContent } { option.additionalContent }
</PayPalRdbWithContent> </PayPalRdbWithContent>
) ) } ) ) }
</> </SettingsBlock>
),
] }
/>
); );
export default RadioSettingsBlock; export default RadioSettingsBlock;

View file

@ -35,12 +35,7 @@ const SelectSettingsBlock = ( {
order = DEFAULT_ELEMENT_ORDER, order = DEFAULT_ELEMENT_ORDER,
...props ...props
} ) => ( } ) => (
<SettingsBlock <SettingsBlock { ...props } className="ppcp-r-settings-block__select">
{ ...props }
className="ppcp-r-settings-block__select"
components={ [
() => (
<>
{ order.map( ( elementKey ) => { { order.map( ( elementKey ) => {
const RenderElement = ELEMENT_RENDERERS[ elementKey ]; const RenderElement = ELEMENT_RENDERERS[ elementKey ];
return RenderElement ? ( return RenderElement ? (
@ -52,10 +47,7 @@ const SelectSettingsBlock = ( {
/> />
) : null; ) : null;
} ) } } ) }
</> </SettingsBlock>
),
] }
/>
); );
export default SelectSettingsBlock; export default SelectSettingsBlock;

View file

@ -1,16 +1,9 @@
const SettingsBlock = ( { className, components = [], children } ) => { const SettingsBlock = ( { className, children } ) => {
const blockClassName = [ 'ppcp-r-settings-block', className ].filter( const blockClassName = [ 'ppcp-r-settings-block', className ].filter(
Boolean Boolean
); );
return ( return <div className={ blockClassName.join( ' ' ) }>{ children }</div>;
<div className={ blockClassName.join( ' ' ) }>
{ children ||
components.map( ( Component, index ) => (
<Component key={ index } />
) ) }
</div>
);
}; };
export default SettingsBlock; export default SettingsBlock;

View file

@ -3,11 +3,7 @@ import SettingsBlock from './SettingsBlock';
import { Header, Title, Action, Description } from './SettingsBlockElements'; import { Header, Title, Action, Description } from './SettingsBlockElements';
const ToggleSettingsBlock = ( { title, description, ...props } ) => ( const ToggleSettingsBlock = ( { title, description, ...props } ) => (
<SettingsBlock <SettingsBlock { ...props } className="ppcp-r-settings-block__toggle">
{ ...props }
className="ppcp-r-settings-block__toggle"
components={ [
() => (
<Action> <Action>
<ToggleControl <ToggleControl
className="ppcp-r-settings-block__toggle-control" className="ppcp-r-settings-block__toggle-control"
@ -21,17 +17,11 @@ const ToggleSettingsBlock = ( { title, description, ...props } ) => (
} }
/> />
</Action> </Action>
),
() => (
<Header> <Header>
{ title && <Title>{ title }</Title> } { title && <Title>{ title }</Title> }
{ description && ( { description && <Description>{ description }</Description> }
<Description>{ description }</Description>
) }
</Header> </Header>
), </SettingsBlock>
] }
/>
); );
export default ToggleSettingsBlock; export default ToggleSettingsBlock;

View file

@ -9,16 +9,10 @@ import {
const OrderIntent = ( { updateFormValue, settings } ) => { const OrderIntent = ( { updateFormValue, settings } ) => {
return ( return (
<SettingsBlock <SettingsBlock>
components={ [
() => (
<>
<Header> <Header>
<Title> <Title>
{ __( { __( 'Order Intent', 'woocommerce-paypal-payments' ) }
'Order Intent',
'woocommerce-paypal-payments'
) }
</Title> </Title>
<Description> <Description>
{ __( { __(
@ -27,15 +21,9 @@ const OrderIntent = ( { updateFormValue, settings } ) => {
) } ) }
</Description> </Description>
</Header> </Header>
</>
),
() => (
<>
<ToggleSettingsBlock <ToggleSettingsBlock
title={ __( title={ __( 'Authorize Only', 'woocommerce-paypal-payments' ) }
'Authorize Only',
'woocommerce-paypal-payments'
) }
actionProps={ { actionProps={ {
callback: updateFormValue, callback: updateFormValue,
key: 'authorizeOnly', key: 'authorizeOnly',
@ -54,10 +42,7 @@ const OrderIntent = ( { updateFormValue, settings } ) => {
value: settings.captureVirtualOnlyOrders, value: settings.captureVirtualOnlyOrders,
} } } }
/> />
</> </SettingsBlock>
),
] }
/>
); );
}; };

View file

@ -1,19 +1,15 @@
import { __, sprintf } from '@wordpress/i18n'; import { __, sprintf } from '@wordpress/i18n';
import { import {
Header,
SettingsBlock, SettingsBlock,
ToggleSettingsBlock, ToggleSettingsBlock,
Title, Title,
Description, Description,
} from '../../../../ReusableComponents/SettingsBlocks'; } from '../../../../ReusableComponents/SettingsBlocks';
import { Header } from '../../../../ReusableComponents/SettingsBlocks/SettingsBlockElements';
const SavePaymentMethods = ( { updateFormValue, settings } ) => { const SavePaymentMethods = ( { updateFormValue, settings } ) => {
return ( return (
<SettingsBlock <SettingsBlock className="ppcp-r-settings-block--save-payment-methods">
className="ppcp-r-settings-block--save-payment-methods"
components={ [
() => (
<>
<Header> <Header>
<Title> <Title>
{ __( { __(
@ -23,14 +19,12 @@ const SavePaymentMethods = ( { updateFormValue, settings } ) => {
</Title> </Title>
<Description> <Description>
{ __( { __(
'Securely store customers payment methods for future payments and subscriptions, simplifying checkout and enabling recurring transactions.', "Securely store customers' payment methods for future payments and subscriptions, simplifying checkout and enabling recurring transactions.",
'woocommerce-paypal-payments' 'woocommerce-paypal-payments'
) } ) }
</Description> </Description>
</Header> </Header>
</>
),
() => (
<ToggleSettingsBlock <ToggleSettingsBlock
title={ __( title={ __(
'Save PayPal and Venmo', 'Save PayPal and Venmo',
@ -57,8 +51,7 @@ const SavePaymentMethods = ( { updateFormValue, settings } ) => {
key: 'savePaypalAndVenmo', key: 'savePaypalAndVenmo',
} } } }
/> />
),
() => (
<ToggleSettingsBlock <ToggleSettingsBlock
title={ __( title={ __(
'Save Credit and Debit Cards', 'Save Credit and Debit Cards',
@ -74,9 +67,7 @@ const SavePaymentMethods = ( { updateFormValue, settings } ) => {
value: settings.saveCreditCardAndDebitCard, value: settings.saveCreditCardAndDebitCard,
} } } }
/> />
), </SettingsBlock>
] }
/>
); );
}; };

View file

@ -36,10 +36,7 @@ const Troubleshooting = ( { updateFormValue, settings } ) => {
value: settings.logging, value: settings.logging,
} } } }
/> />
<SettingsBlock <SettingsBlock>
components={ [
() => (
<>
<Header> <Header>
<Title> <Title>
{ __( { __(
@ -62,10 +59,7 @@ const Troubleshooting = ( { updateFormValue, settings } ) => {
</Description> </Description>
</Header> </Header>
<HooksTable data={ hooksExampleData() } /> <HooksTable data={ hooksExampleData() } />
</> </SettingsBlock>
),
] }
/>
<ButtonSettingsBlock <ButtonSettingsBlock
title={ __( title={ __(