woocommerce/plugins/woocommerce-blocks/assets/js/base/context/hooks/use-checkout-address.js

126 lines
3.2 KiB
JavaScript

/**
* External dependencies
*/
import { defaultAddressFields } from '@woocommerce/settings';
import { useEffect, useCallback, useRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import {
useShippingDataContext,
useCustomerDataContext,
} from '../providers/cart-checkout';
/**
* Custom hook for exposing address related functionality for the checkout address form.
*/
export const useCheckoutAddress = () => {
const { needsShipping } = useShippingDataContext();
const {
billingData,
setBillingData,
shippingAddress,
setShippingAddress,
shippingAsBilling,
setShippingAsBilling,
} = useCustomerDataContext();
const currentShippingAsBilling = useRef( shippingAsBilling );
const previousBillingData = useRef( billingData );
/**
* Sets shipping address data, and also billing if using the same address.
*/
const setShippingFields = useCallback(
( value ) => {
setShippingAddress( value );
if ( shippingAsBilling ) {
setBillingData( value );
}
},
[ shippingAsBilling, setShippingAddress, setBillingData ]
);
/**
* Sets billing address data, and also shipping if shipping is disabled.
*/
const setBillingFields = useCallback(
( value ) => {
setBillingData( value );
if ( ! needsShipping ) {
setShippingAddress( value );
}
},
[ needsShipping, setShippingAddress, setBillingData ]
);
// When the "Use same address" checkbox is toggled we need to update the current billing address to reflect this.
// This either sets the billing address to the shipping address, or restores the billing address to it's previous state.
useEffect( () => {
if ( currentShippingAsBilling.current !== shippingAsBilling ) {
if ( shippingAsBilling ) {
previousBillingData.current = billingData;
setBillingData( shippingAddress );
} else {
const {
// We need to pluck out email from previous billing data because they can be empty, causing the current email to get emptied. See issue #4155
/* eslint-disable no-unused-vars */
email,
/* eslint-enable no-unused-vars */
...billingAddress
} = previousBillingData.current;
setBillingData( {
...billingAddress,
} );
}
currentShippingAsBilling.current = shippingAsBilling;
}
}, [ shippingAsBilling, setBillingData, shippingAddress, billingData ] );
const setEmail = useCallback(
( value ) =>
void setBillingData( {
email: value,
} ),
[ setBillingData ]
);
const setPhone = useCallback(
( value ) =>
void setBillingData( {
phone: value,
} ),
[ setBillingData ]
);
const setShippingPhone = useCallback(
( value ) =>
void setShippingFields( {
phone: value,
} ),
[ setShippingFields ]
);
// Note that currentShippingAsBilling is returned rather than the current state of shippingAsBilling--this is so that
// the billing fields are not rendered before sync (billing field values are debounced and would be outdated)
return {
defaultAddressFields,
shippingFields: shippingAddress,
setShippingFields,
billingFields: billingData,
setBillingFields,
setEmail,
setPhone,
setShippingPhone,
shippingAsBilling,
setShippingAsBilling,
showShippingFields: needsShipping,
showBillingFields:
! needsShipping || ! currentShippingAsBilling.current,
};
};