/** * External dependencies */ import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data'; import { useSelect } from '@wordpress/data'; import { Cart } from '@woocommerce/type-defs/cart'; import { SelectShippingRateType } from '@woocommerce/type-defs/shipping'; import { useEffect, useRef } from '@wordpress/element'; import { deriveSelectedShippingRates } from '@woocommerce/base-utils'; import isShallowEqual from '@wordpress/is-shallow-equal'; import { isObject } from '@woocommerce/types'; /** * Internal dependencies */ import { useSelectShippingRate } from './use-select-shipping-rate'; interface ShippingData extends SelectShippingRateType { needsShipping: Cart[ 'needsShipping' ]; hasCalculatedShipping: Cart[ 'hasCalculatedShipping' ]; shippingRates: Cart[ 'shippingRates' ]; isLoadingRates: boolean; selectedRates: Record< string, string | unknown >; } export const useShippingData = (): ShippingData => { const { shippingRates, needsShipping, hasCalculatedShipping, isLoadingRates, } = useSelect( ( select ) => { const store = select( storeKey ); return { shippingRates: store.getShippingRates(), needsShipping: store.getNeedsShipping(), hasCalculatedShipping: store.getHasCalculatedShipping(), isLoadingRates: store.isCustomerDataUpdating(), }; } ); const { isSelectingRate, selectShippingRate } = useSelectShippingRate(); // set selected rates on ref so it's always current. const selectedRates = useRef< Record< string, unknown > >( {} ); useEffect( () => { const derivedSelectedRates = deriveSelectedShippingRates( shippingRates ); if ( isObject( derivedSelectedRates ) && ! isShallowEqual( selectedRates.current, derivedSelectedRates ) ) { selectedRates.current = derivedSelectedRates; } }, [ shippingRates ] ); return { isSelectingRate, selectedRates: selectedRates.current, selectShippingRate, shippingRates, needsShipping, hasCalculatedShipping, isLoadingRates, }; };