Fix 'Country is required' error on the Cart block when updating shipping address (https://github.com/woocommerce/woocommerce-blocks/pull/5129)

* Fix  error on the Cart block

* Created a cartIsHydrated variable in useStoreCart hook and used this to update the billing address in the internal state of the useCustomerData hook

* Fix the country is required error on the Cart page using refs

* Separate api calls to update shipping and billingUpdate billing and shipping addresses only when needed in API calls

* Remove redundant check for customerDataToUpdate

* remove use of refs in initial values

Co-authored-by: Nadir Seghir <nadir.seghir@gmail.com>
This commit is contained in:
Alex Florisca 2021-11-16 12:39:43 +00:00 committed by GitHub
parent f9c458b090
commit 78c846bddc
4 changed files with 63 additions and 23 deletions

View File

@ -184,6 +184,7 @@ export const useStoreCart = (
const cartIsLoading = ! store.hasFinishedResolution(
'getCartData'
);
const shippingRatesLoading = store.isCustomerDataUpdating();
const { receiveCart } = dispatch( storeKey );
const billingAddress = decodeValues( cartData.billingAddress );

View File

@ -11,9 +11,12 @@ import {
pluckAddress,
pluckEmail,
} from '@woocommerce/base-utils';
import type {
import {
CartResponseBillingAddress,
CartResponseShippingAddress,
BillingAddressShippingAddress,
CartBillingAddress,
CartShippingAddress,
} from '@woocommerce/types';
declare type CustomerData = {
@ -92,6 +95,26 @@ export const useCustomerData = (): {
shippingAddress: initialShippingAddress,
} );
// We only want to update the local state once, otherwise the data on the checkout page gets overwritten
// with the initial state of the addresses here
const [ hasCustomerDataSynced, setHasCustomerDataSynced ] = useState<
boolean
>( false );
if (
! hasCustomerDataSynced &&
shouldUpdateAddressStore(
customerData.shippingAddress,
initialShippingAddress
)
) {
setCustomerData( {
billingData: initialBillingAddress,
shippingAddress: initialShippingAddress,
} );
setHasCustomerDataSynced( true );
}
// Store values last sent to the server in a ref to avoid requests unless important fields are changed.
const previousCustomerData = useRef< CustomerData >( customerData );
@ -146,23 +169,40 @@ export const useCustomerData = (): {
*/
useEffect( () => {
// Only push updates when enough fields are populated.
if (
! shouldUpdateAddressStore(
previousCustomerData.current.billingData,
debouncedCustomerData.billingData
) &&
! shouldUpdateAddressStore(
previousCustomerData.current.shippingAddress,
debouncedCustomerData.shippingAddress
)
) {
const shouldUpdateBillingAddress = shouldUpdateAddressStore(
previousCustomerData.current.billingData,
debouncedCustomerData.billingData
);
const shouldUpdateShippingAddress = shouldUpdateAddressStore(
previousCustomerData.current.shippingAddress,
debouncedCustomerData.shippingAddress
);
if ( ! shouldUpdateBillingAddress && ! shouldUpdateShippingAddress ) {
return;
}
const customerDataToUpdate:
| Partial< BillingAddressShippingAddress >
| Record<
keyof BillingAddressShippingAddress,
CartBillingAddress | CartShippingAddress
> = {};
if ( shouldUpdateBillingAddress ) {
customerDataToUpdate.billing_address =
debouncedCustomerData.billingData;
}
if ( shouldUpdateShippingAddress ) {
customerDataToUpdate.shipping_address =
debouncedCustomerData.shippingAddress;
}
previousCustomerData.current = debouncedCustomerData;
updateCustomerData( {
billing_address: debouncedCustomerData.billingData,
shipping_address: debouncedCustomerData.shippingAddress,
} )
updateCustomerData(
customerDataToUpdate as Partial< BillingAddressShippingAddress >
)
.then( () => {
removeNotice( 'checkout' );
} )

View File

@ -6,9 +6,8 @@ import type {
Cart,
CartResponse,
CartResponseItem,
CartBillingAddress,
CartShippingAddress,
ExtensionCartUpdateArgs,
BillingAddressShippingAddress,
} from '@woocommerce/types';
import { ReturnOrGeneratorYieldUnion } from '@automattic/data-stores';
import { camelCase, mapKeys } from 'lodash';
@ -463,11 +462,6 @@ export function* selectShippingRate(
return true;
}
type BillingAddressShippingAddress = {
billing_address: CartBillingAddress;
shipping_address: CartShippingAddress;
};
/**
* Updates the shipping and/or billing address for the customer and returns an
* updated cart.
@ -476,7 +470,7 @@ type BillingAddressShippingAddress = {
* billing_address and shipping_address.
*/
export function* updateCustomerData(
customerData: BillingAddressShippingAddress
customerData: Partial< BillingAddressShippingAddress >
): Generator< unknown, boolean, { response: CartResponse } > {
yield updatingCustomerData( true );

View File

@ -198,3 +198,8 @@ export interface ExtensionCartUpdateArgs {
data: Record< string, unknown >;
namespace: string;
}
export interface BillingAddressShippingAddress {
billing_address: CartBillingAddress;
shipping_address: CartShippingAddress;
}