Add optimizations around checkout filter calls (https://github.com/woocommerce/woocommerce-blocks/pull/4570)
* Extract productPriceValidation out of the component * Extract checkout filter args outside of component * Remove unnecessary default fallback * Mark ProductName optional props as not required * Use an empty array constant for the filteredNotices default value when there are no notices * Refactor Panel component so hidden contents are not rendered * Prevent extensions changing on each call of __experimentalApplyCheckoutFilter if it was an empty object * Add missing line break * Update tests
This commit is contained in:
parent
ff9c73bec5
commit
70ec1f8b31
|
@ -13,7 +13,7 @@ import {
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Dinero from 'dinero.js';
|
import Dinero from 'dinero.js';
|
||||||
import { getSetting } from '@woocommerce/settings';
|
import { getSetting } from '@woocommerce/settings';
|
||||||
import { useCallback, useMemo } from '@wordpress/element';
|
import { useMemo } from '@wordpress/element';
|
||||||
import { useStoreCart } from '@woocommerce/base-context/hooks';
|
import { useStoreCart } from '@woocommerce/base-context/hooks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,21 +24,23 @@ import ProductImage from '../product-image';
|
||||||
import ProductLowStockBadge from '../product-low-stock-badge';
|
import ProductLowStockBadge from '../product-low-stock-badge';
|
||||||
import ProductMetadata from '../product-metadata';
|
import ProductMetadata from '../product-metadata';
|
||||||
|
|
||||||
|
const productPriceValidation = ( value ) => mustContain( value, '<price/>' );
|
||||||
|
|
||||||
const OrderSummaryItem = ( { cartItem } ) => {
|
const OrderSummaryItem = ( { cartItem } ) => {
|
||||||
const {
|
const {
|
||||||
images,
|
images,
|
||||||
low_stock_remaining: lowStockRemaining = null,
|
low_stock_remaining: lowStockRemaining,
|
||||||
show_backorder_badge: showBackorderBadge = false,
|
show_backorder_badge: showBackorderBadge,
|
||||||
name: initialName,
|
name: initialName,
|
||||||
permalink,
|
permalink,
|
||||||
prices,
|
prices,
|
||||||
quantity,
|
quantity,
|
||||||
short_description: shortDescription,
|
short_description: shortDescription,
|
||||||
description: fullDescription,
|
description: fullDescription,
|
||||||
item_data: itemData = [],
|
item_data: itemData,
|
||||||
variation,
|
variation,
|
||||||
totals,
|
totals,
|
||||||
extensions = {},
|
extensions,
|
||||||
} = cartItem;
|
} = cartItem;
|
||||||
|
|
||||||
// Prepare props to pass to the __experimentalApplyCheckoutFilter filter.
|
// Prepare props to pass to the __experimentalApplyCheckoutFilter filter.
|
||||||
|
@ -46,11 +48,6 @@ const OrderSummaryItem = ( { cartItem } ) => {
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const { receiveCart, ...cart } = useStoreCart();
|
const { receiveCart, ...cart } = useStoreCart();
|
||||||
|
|
||||||
const productPriceValidation = useCallback(
|
|
||||||
( value ) => mustContain( value, '<price/>' ),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const arg = useMemo(
|
const arg = useMemo(
|
||||||
() => ( {
|
() => ( {
|
||||||
context: 'summary',
|
context: 'summary',
|
||||||
|
|
|
@ -12,7 +12,7 @@ import OrderSummary from '../index';
|
||||||
jest.mock( '@woocommerce/base-context', () => ( {
|
jest.mock( '@woocommerce/base-context', () => ( {
|
||||||
...jest.requireActual( '@woocommerce/base-context' ),
|
...jest.requireActual( '@woocommerce/base-context' ),
|
||||||
useContainerWidthContext: () => ( {
|
useContainerWidthContext: () => ( {
|
||||||
isLarge: false,
|
isLarge: true,
|
||||||
hasContainerWidth: true,
|
hasContainerWidth: true,
|
||||||
} ),
|
} ),
|
||||||
} ) );
|
} ) );
|
||||||
|
|
|
@ -16,6 +16,10 @@ import { getSetting } from '@woocommerce/settings';
|
||||||
*/
|
*/
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
|
const filteredCartCouponsFilterArg = {
|
||||||
|
context: 'summary',
|
||||||
|
};
|
||||||
|
|
||||||
const TotalsDiscount = ( {
|
const TotalsDiscount = ( {
|
||||||
cartCoupons = [],
|
cartCoupons = [],
|
||||||
currency,
|
currency,
|
||||||
|
@ -42,9 +46,7 @@ const TotalsDiscount = ( {
|
||||||
: discountValue;
|
: discountValue;
|
||||||
|
|
||||||
const filteredCartCoupons = __experimentalApplyCheckoutFilter( {
|
const filteredCartCoupons = __experimentalApplyCheckoutFilter( {
|
||||||
arg: {
|
arg: filteredCartCouponsFilterArg,
|
||||||
context: 'summary',
|
|
||||||
},
|
|
||||||
filterName: 'coupons',
|
filterName: 'coupons',
|
||||||
defaultValue: cartCoupons,
|
defaultValue: cartCoupons,
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -21,10 +21,10 @@ export default ( {
|
||||||
permalink = '',
|
permalink = '',
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
className: string;
|
className?: string;
|
||||||
disabled: boolean;
|
disabled?: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
permalink: string;
|
permalink?: string;
|
||||||
} ): JSX.Element => {
|
} ): JSX.Element => {
|
||||||
const classes = classnames( 'wc-block-components-product-name', className );
|
const classes = classnames( 'wc-block-components-product-name', className );
|
||||||
return disabled ? (
|
return disabled ? (
|
||||||
|
|
|
@ -5,6 +5,8 @@ import { SnackbarList } from 'wordpress-components';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { __experimentalApplyCheckoutFilter } from '@woocommerce/blocks-checkout';
|
import { __experimentalApplyCheckoutFilter } from '@woocommerce/blocks-checkout';
|
||||||
|
|
||||||
|
const EMPTY_SNACKBAR_NOTICES = {};
|
||||||
|
|
||||||
const SnackbarNoticesContainer = ( {
|
const SnackbarNoticesContainer = ( {
|
||||||
className,
|
className,
|
||||||
notices,
|
notices,
|
||||||
|
@ -19,10 +21,13 @@ const SnackbarNoticesContainer = ( {
|
||||||
( notice ) => notice.type === 'snackbar'
|
( notice ) => notice.type === 'snackbar'
|
||||||
);
|
);
|
||||||
|
|
||||||
const noticeVisibility = snackbarNotices.reduce( ( acc, { content } ) => {
|
const noticeVisibility =
|
||||||
acc[ content ] = true;
|
snackbarNotices.length > 0
|
||||||
return acc;
|
? snackbarNotices.reduce( ( acc, { content } ) => {
|
||||||
}, {} );
|
acc[ content ] = true;
|
||||||
|
return acc;
|
||||||
|
}, {} )
|
||||||
|
: EMPTY_SNACKBAR_NOTICES;
|
||||||
|
|
||||||
const filteredNotices = __experimentalApplyCheckoutFilter( {
|
const filteredNotices = __experimentalApplyCheckoutFilter( {
|
||||||
filterName: 'snackbarNoticeVisibility',
|
filterName: 'snackbarNoticeVisibility',
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {
|
||||||
mustContain,
|
mustContain,
|
||||||
} from '@woocommerce/blocks-checkout';
|
} from '@woocommerce/blocks-checkout';
|
||||||
import Dinero from 'dinero.js';
|
import Dinero from 'dinero.js';
|
||||||
import { useCallback, useMemo } from '@wordpress/element';
|
import { useMemo } from '@wordpress/element';
|
||||||
import type { CartItem } from '@woocommerce/type-defs/cart';
|
import type { CartItem } from '@woocommerce/type-defs/cart';
|
||||||
import { objectHasProp } from '@woocommerce/types';
|
import { objectHasProp } from '@woocommerce/types';
|
||||||
import { getSetting } from '@woocommerce/settings';
|
import { getSetting } from '@woocommerce/settings';
|
||||||
|
@ -46,6 +46,8 @@ const getAmountFromRawPrice = (
|
||||||
return priceObject.convertPrecision( currency.minorUnit ).getAmount();
|
return priceObject.convertPrecision( currency.minorUnit ).getAmount();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const productPriceValidation = ( value ) => mustContain( value, '<price/>' );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cart line item table row component.
|
* Cart line item table row component.
|
||||||
*
|
*
|
||||||
|
@ -99,7 +101,7 @@ const CartLineItemRow = ( {
|
||||||
line_subtotal: '0',
|
line_subtotal: '0',
|
||||||
line_subtotal_tax: '0',
|
line_subtotal_tax: '0',
|
||||||
},
|
},
|
||||||
extensions = {},
|
extensions,
|
||||||
} = lineItem;
|
} = lineItem;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -110,11 +112,6 @@ const CartLineItemRow = ( {
|
||||||
} = useStoreCartItemQuantity( lineItem );
|
} = useStoreCartItemQuantity( lineItem );
|
||||||
const { dispatchStoreEvent } = useStoreEvents();
|
const { dispatchStoreEvent } = useStoreEvents();
|
||||||
|
|
||||||
const productPriceValidation = useCallback(
|
|
||||||
( value ) => mustContain( value, '<price/>' ),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Prepare props to pass to the __experimentalApplyCheckoutFilter filter.
|
// Prepare props to pass to the __experimentalApplyCheckoutFilter filter.
|
||||||
// We need to pluck out receiveCart.
|
// We need to pluck out receiveCart.
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
@ -308,4 +305,5 @@ const CartLineItemRow = ( {
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CartLineItemRow;
|
export default CartLineItemRow;
|
||||||
|
|
|
@ -427,57 +427,6 @@ exports[`Testing cart Contains a Taxes section if Core options are set to show i
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="wc-block-components-panel__content"
|
|
||||||
hidden=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-hidden="false"
|
|
||||||
class=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="wc-block-components-totals-coupon__content"
|
|
||||||
>
|
|
||||||
<form
|
|
||||||
class="wc-block-components-totals-coupon__form"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="wc-block-components-text-input wc-block-components-totals-coupon__input is-active"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
aria-describedby=""
|
|
||||||
aria-label="Enter code"
|
|
||||||
autocapitalize="off"
|
|
||||||
autocomplete="off"
|
|
||||||
id="wc-block-components-totals-coupon__input-1"
|
|
||||||
type="text"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="wc-block-components-totals-coupon__input-1"
|
|
||||||
>
|
|
||||||
Enter code
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="components-button wc-block-components-button wc-block-components-totals-coupon__button"
|
|
||||||
disabled=""
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="wc-block-components-button__text"
|
|
||||||
>
|
|
||||||
Apply
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -1160,57 +1109,6 @@ exports[`Testing cart Shows individual tax lines if the store is set to do so 1`
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="wc-block-components-panel__content"
|
|
||||||
hidden=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-hidden="false"
|
|
||||||
class=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="wc-block-components-totals-coupon__content"
|
|
||||||
>
|
|
||||||
<form
|
|
||||||
class="wc-block-components-totals-coupon__form"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="wc-block-components-text-input wc-block-components-totals-coupon__input is-active"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
aria-describedby=""
|
|
||||||
aria-label="Enter code"
|
|
||||||
autocapitalize="off"
|
|
||||||
autocomplete="off"
|
|
||||||
id="wc-block-components-totals-coupon__input-2"
|
|
||||||
type="text"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="wc-block-components-totals-coupon__input-2"
|
|
||||||
>
|
|
||||||
Enter code
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="components-button wc-block-components-button wc-block-components-totals-coupon__button"
|
|
||||||
disabled=""
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="wc-block-components-button__text"
|
|
||||||
>
|
|
||||||
Apply
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -1898,57 +1796,6 @@ exports[`Testing cart Shows rate percentages after tax lines if the block is set
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="wc-block-components-panel__content"
|
|
||||||
hidden=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-hidden="false"
|
|
||||||
class=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="wc-block-components-totals-coupon__content"
|
|
||||||
>
|
|
||||||
<form
|
|
||||||
class="wc-block-components-totals-coupon__form"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="wc-block-components-text-input wc-block-components-totals-coupon__input is-active"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
aria-describedby=""
|
|
||||||
aria-label="Enter code"
|
|
||||||
autocapitalize="off"
|
|
||||||
autocomplete="off"
|
|
||||||
id="wc-block-components-totals-coupon__input-3"
|
|
||||||
type="text"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="wc-block-components-totals-coupon__input-3"
|
|
||||||
>
|
|
||||||
Enter code
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="components-button wc-block-components-button wc-block-components-totals-coupon__button"
|
|
||||||
disabled=""
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="wc-block-components-button__text"
|
|
||||||
>
|
|
||||||
Apply
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -63,57 +63,6 @@ exports[`Testing checkout sidebar Shows rate percentages after tax lines if the
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="wc-block-components-panel__content"
|
|
||||||
hidden=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-hidden="false"
|
|
||||||
class=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="wc-block-components-totals-coupon__content"
|
|
||||||
>
|
|
||||||
<form
|
|
||||||
class="wc-block-components-totals-coupon__form"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="wc-block-components-text-input wc-block-components-totals-coupon__input is-active"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
aria-describedby="wc-block-components-totals-coupon__input-0"
|
|
||||||
aria-label="Enter code"
|
|
||||||
autocapitalize="off"
|
|
||||||
autocomplete="off"
|
|
||||||
id="wc-block-components-totals-coupon__input-0"
|
|
||||||
type="text"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="wc-block-components-totals-coupon__input-0"
|
|
||||||
>
|
|
||||||
Enter code
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
class="components-button wc-block-components-button wc-block-components-totals-coupon__button"
|
|
||||||
disabled=""
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="wc-block-components-button__text"
|
|
||||||
>
|
|
||||||
Apply
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -50,12 +50,11 @@ const Panel = ( {
|
||||||
{ title }
|
{ title }
|
||||||
</button>
|
</button>
|
||||||
</TitleTag>
|
</TitleTag>
|
||||||
<div
|
{ isOpen && (
|
||||||
className="wc-block-components-panel__content"
|
<div className="wc-block-components-panel__content">
|
||||||
hidden={ ! isOpen }
|
{ children }
|
||||||
>
|
</div>
|
||||||
{ children }
|
) }
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -90,7 +90,7 @@ const getCheckoutFilters = ( filterName: string ): CheckoutFilterFunction[] => {
|
||||||
export const __experimentalApplyCheckoutFilter = < T >( {
|
export const __experimentalApplyCheckoutFilter = < T >( {
|
||||||
filterName,
|
filterName,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
extensions = {},
|
extensions = null,
|
||||||
arg = null,
|
arg = null,
|
||||||
validation = returnTrue,
|
validation = returnTrue,
|
||||||
}: {
|
}: {
|
||||||
|
@ -99,7 +99,7 @@ export const __experimentalApplyCheckoutFilter = < T >( {
|
||||||
/** Default value to filter. */
|
/** Default value to filter. */
|
||||||
defaultValue: T;
|
defaultValue: T;
|
||||||
/** Values extend to REST API response. */
|
/** Values extend to REST API response. */
|
||||||
extensions?: Record< string, unknown >;
|
extensions?: Record< string, unknown > | null;
|
||||||
/** Object containing arguments for the filter function. */
|
/** Object containing arguments for the filter function. */
|
||||||
arg?: CheckoutFilterArguments;
|
arg?: CheckoutFilterArguments;
|
||||||
/** Function that needs to return true when the filtered value is passed in order for the filter to be applied. */
|
/** Function that needs to return true when the filtered value is passed in order for the filter to be applied. */
|
||||||
|
@ -111,7 +111,7 @@ export const __experimentalApplyCheckoutFilter = < T >( {
|
||||||
let value = defaultValue;
|
let value = defaultValue;
|
||||||
filters.forEach( ( filter ) => {
|
filters.forEach( ( filter ) => {
|
||||||
try {
|
try {
|
||||||
const newValue = filter( value, extensions, arg );
|
const newValue = filter( value, extensions || {}, arg );
|
||||||
if ( typeof newValue !== typeof value ) {
|
if ( typeof newValue !== typeof value ) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
sprintf(
|
sprintf(
|
||||||
|
|
Loading…
Reference in New Issue