Commit 1c67ffce1f3 for woocommerce
commit 1c67ffce1f35f79091c74bd9dd67862796b7a689
Author: Karol Manijak <20098064+kmanijak@users.noreply.github.com>
Date: Tue Jun 30 15:06:28 2026 +0200
Fix Product Collection filter resets (#66022)
* Fix Product Collection filter resets
* Add changelog entry for Product Collection reset fix
* Guard Product Collection tax query updates
diff --git a/plugins/woocommerce/changelog/fix-59238-product-collection-reset-all b/plugins/woocommerce/changelog/fix-59238-product-collection-reset-all
new file mode 100644
index 00000000000..7170b34d783
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-59238-product-collection-reset-all
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prevent Product Collection filter resets from clearing lifted collection controls.
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/index.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/index.tsx
index 1d8376539af..d33f4b3208b 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/index.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/index.tsx
@@ -249,7 +249,7 @@ const ProductCollectionInspectorControls = (
{ showCustomQueryControls ? (
<ToolsPanel
label={ __( 'Filters', 'woocommerce' ) }
- resetAll={ ( resetAllFilters: ( () => void )[] ) => {
+ resetAll={ ( resetAllFilters = [] ) => {
resetAllFilters.forEach( ( resetFilter ) => {
resetFilter();
} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/taxonomy-controls/use-taxonomy-controls.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/taxonomy-controls/use-taxonomy-controls.tsx
index f5454f61abe..ea9207427c2 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/taxonomy-controls/use-taxonomy-controls.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/inspector-controls/taxonomy-controls/use-taxonomy-controls.tsx
@@ -67,7 +67,6 @@ function useTaxonomyControls( {
const createHandleChange = ( slug: string ) => ( newTermIds: number[] ) => {
setQueryAttribute( {
taxQuery: {
- ...taxQuery,
[ slug ]: newTermIds,
},
} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/taxonomy-picker.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/taxonomy-picker.tsx
index b88ac9c7dc8..581f5d408b3 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/taxonomy-picker.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/edit/taxonomy-picker.tsx
@@ -106,7 +106,6 @@ const TaxonomyPicker = ( props: TaxonomyPickerProps ) => {
const handleTermChange = ( termIds: number[] ) => {
setQueryAttribute( props, {
taxQuery: {
- ...attributes.query?.taxQuery,
[ taxonomySlug ]: termIds,
},
} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/test/query-attributes.ts b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/test/query-attributes.ts
new file mode 100644
index 00000000000..da0cd4190fa
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/test/query-attributes.ts
@@ -0,0 +1,102 @@
+/**
+ * Internal dependencies
+ */
+import { DEFAULT_QUERY } from '../constants';
+import { ProductCollectionQuery } from '../types';
+import { getUpdatedQuery } from '../utils';
+
+const getQuery = (
+ query: Partial< ProductCollectionQuery > = {}
+): ProductCollectionQuery => ( {
+ ...DEFAULT_QUERY,
+ ...query,
+} );
+
+describe( 'getUpdatedQuery', () => {
+ it( 'updates query attributes', () => {
+ expect(
+ getUpdatedQuery(
+ getQuery( {
+ search: 'shirt',
+ woocommerceOnSale: true,
+ } ),
+ {
+ woocommerceOnSale: false,
+ }
+ )
+ ).toEqual(
+ getQuery( {
+ search: 'shirt',
+ woocommerceOnSale: false,
+ } )
+ );
+ } );
+
+ it( 'merges taxQuery updates into the current taxQuery', () => {
+ expect(
+ getUpdatedQuery(
+ getQuery( {
+ taxQuery: {
+ product_cat: [ 1 ],
+ product_tag: [ 2 ],
+ },
+ } ),
+ {
+ taxQuery: {
+ product_tag: [],
+ },
+ }
+ ).taxQuery
+ ).toEqual( {
+ product_cat: [ 1 ],
+ product_tag: [],
+ } );
+ } );
+
+ it( 'preserves taxQuery when an update does not include taxonomy changes', () => {
+ expect(
+ getUpdatedQuery(
+ getQuery( {
+ taxQuery: {
+ product_cat: [ 1 ],
+ product_tag: [ 2 ],
+ },
+ } ),
+ {
+ woocommerceOnSale: true,
+ }
+ ).taxQuery
+ ).toEqual( {
+ product_cat: [ 1 ],
+ product_tag: [ 2 ],
+ } );
+ } );
+
+ it( 'preserves taxQuery when a taxonomy update is invalid', () => {
+ const query = getQuery( {
+ taxQuery: {
+ product_cat: [ 1 ],
+ product_tag: [ 2 ],
+ },
+ } );
+
+ expect(
+ getUpdatedQuery( query, {
+ taxQuery: undefined,
+ } ).taxQuery
+ ).toEqual( {
+ product_cat: [ 1 ],
+ product_tag: [ 2 ],
+ } );
+
+ expect(
+ getUpdatedQuery( query, {
+ taxQuery:
+ null as unknown as ProductCollectionQuery[ 'taxQuery' ],
+ } ).taxQuery
+ ).toEqual( {
+ product_cat: [ 1 ],
+ product_tag: [ 2 ],
+ } );
+ } );
+} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/utils.tsx b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/utils.tsx
index 661f3df7cf9..62daf105787 100644
--- a/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/utils.tsx
+++ b/plugins/woocommerce/client/blocks/assets/js/blocks/product-collection/utils.tsx
@@ -53,17 +53,38 @@ import {
*
* Shorthand for setting new nested query parameters.
*/
+export const getUpdatedQuery = (
+ query: ProductCollectionQuery,
+ queryParams: Partial< ProductCollectionQuery >
+): ProductCollectionQuery => {
+ const { taxQuery, ...queryParamsWithoutTaxQuery } = queryParams;
+ const hasTaxQueryUpdates =
+ taxQuery && typeof taxQuery === 'object' && ! Array.isArray( taxQuery );
+
+ return {
+ ...query,
+ ...queryParamsWithoutTaxQuery,
+ ...( hasTaxQueryUpdates && {
+ taxQuery: {
+ ...query.taxQuery,
+ ...taxQuery,
+ },
+ } ),
+ };
+};
+
export function setQueryAttribute(
block: BlockEditProps< ProductCollectionAttributes >,
queryParams: Partial< ProductCollectionQuery >
) {
- const { query } = block.attributes;
+ const currentBlock = select( blockEditorStore ).getBlock( block.clientId );
+ const currentAttributes = currentBlock?.attributes as
+ | ProductCollectionAttributes
+ | undefined;
+ const query = currentAttributes?.query || block.attributes.query;
block.setAttributes( {
- query: {
- ...query,
- ...queryParams,
- },
+ query: getUpdatedQuery( query, queryParams ),
} );
}