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

Commit

Permalink
Fix 'Country is required' error on the Cart block when updating shipp…
Browse files Browse the repository at this point in the history
…ing address (#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 <[email protected]>
  • Loading branch information
2 people authored and nielslange committed Nov 17, 2021
1 parent a6c4fd0 commit a274933
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 23 deletions.
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;
}

0 comments on commit a274933

Please sign in to comment.