Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Fix 'Country is required' error on the Cart block when updating shipping address #5129

Merged
merged 6 commits into from
Nov 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions assets/js/base/context/hooks/cart/use-store-cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
70 changes: 55 additions & 15 deletions assets/js/base/context/hooks/use-customer-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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 );

Expand Down Expand Up @@ -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' );
} )
Expand Down
10 changes: 2 additions & 8 deletions assets/js/data/cart/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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.
Expand All @@ -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 );

Expand Down
5 changes: 5 additions & 0 deletions assets/js/types/type-defs/cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,8 @@ export interface ExtensionCartUpdateArgs {
data: Record< string, unknown >;
namespace: string;
}

export interface BillingAddressShippingAddress {
billing_address: CartBillingAddress;
shipping_address: CartShippingAddress;
}