diff --git a/packages/js/product-editor/changelog/add-use-product-metadata b/packages/js/product-editor/changelog/add-use-product-metadata new file mode 100644 index 00000000000..2a7c90e2ce1 --- /dev/null +++ b/packages/js/product-editor/changelog/add-use-product-metadata @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Add useProductMetadata hook to perform update in multiple meta entries at same time diff --git a/packages/js/product-editor/src/hooks/index.ts b/packages/js/product-editor/src/hooks/index.ts index cf3efeb8863..531e68a8f22 100644 --- a/packages/js/product-editor/src/hooks/index.ts +++ b/packages/js/product-editor/src/hooks/index.ts @@ -4,3 +4,4 @@ export { useVariationsOrder as __experimentalUseVariationsOrder } from './use-va export { useCurrencyInputProps as __experimentalUseCurrencyInputProps } from './use-currency-input-props'; export { useVariationSwitcher as __experimentalUseVariationSwitcher } from './use-variation-switcher'; export { default as __experimentalUseProductEntityProp } from './use-product-entity-prop'; +export { default as __experimentalUseProductMetadata } from './use-product-metadata'; diff --git a/packages/js/product-editor/src/hooks/test/use-product-metadata.test.ts b/packages/js/product-editor/src/hooks/test/use-product-metadata.test.ts new file mode 100644 index 00000000000..26b7a5aa7cd --- /dev/null +++ b/packages/js/product-editor/src/hooks/test/use-product-metadata.test.ts @@ -0,0 +1,63 @@ +/** + * External dependencies + */ +import { renderHook } from '@testing-library/react-hooks'; + +/** + * Internal dependencies + */ +import useProductMetadata from '../use-product-metadata'; + +const mockFnMetadataProp = jest.fn(); +jest.mock( '@wordpress/core-data', () => ( { + useEntityProp: jest.fn().mockImplementation( () => { + return [ + [ + { + key: 'field1', + value: 'value1', + }, + { + key: 'field2', + value: 'value1', + }, + { + key: 'existing_field', + value: 'value1', + }, + ], + mockFnMetadataProp, + ]; + } ), +} ) ); + +describe( 'useProductMetadata', () => { + it( 'should update all the metadata with new values and not replace existing fields', async () => { + const { updateMetadata } = renderHook( () => useProductMetadata() ) + .result.current; + updateMetadata( [ + { + key: 'field1', + value: 'value2', + }, + { + key: 'field2', + value: 'value2', + }, + ] ); + expect( mockFnMetadataProp ).toHaveBeenCalledWith( [ + { + key: 'existing_field', + value: 'value1', + }, + { + key: 'field1', + value: 'value2', + }, + { + key: 'field2', + value: 'value2', + }, + ] ); + } ); +} ); diff --git a/packages/js/product-editor/src/hooks/use-product-metadata.ts b/packages/js/product-editor/src/hooks/use-product-metadata.ts new file mode 100644 index 00000000000..69e487caf47 --- /dev/null +++ b/packages/js/product-editor/src/hooks/use-product-metadata.ts @@ -0,0 +1,30 @@ +/** + * External dependencies + */ +import { useEntityProp } from '@wordpress/core-data'; +/** + * Internal dependencies + */ +import { Metadata } from '../types'; + +function useProductMetadata( postType?: string ) { + const [ metadata, setMetadata ] = useEntityProp< Metadata< string >[] >( + 'postType', + postType || 'product', + 'meta_data' + ); + + return { + updateMetadata: ( entries: Metadata< string >[] ) => { + setMetadata( [ + ...metadata.filter( + ( item ) => + entries.findIndex( ( e ) => e.key === item.key ) === -1 + ), + ...entries, + ] ); + }, + }; +} + +export default useProductMetadata;