Remove `useSelectShippingRate` hook and adjust how local state works for `PackageRates` (https://github.com/woocommerce/woocommerce-blocks/pull/5802)
* Convert radio component to TS and support uncontrolled components * Further radio control to typescript changes * Combine useSelectShippingRate and useSelectShippingRates * Remove useSelectShippingRate hook * Move local radio checked state to PackageRates * This is a Controlled component - update inline docs * useSelectShippingRates -> useSelectShippingRate rename
This commit is contained in:
parent
051bb64138
commit
0a8fe0a0c6
|
@ -57,7 +57,7 @@ interface PackageProps {
|
||||||
|
|
||||||
export const ShippingRatesControlPackage = ( {
|
export const ShippingRatesControlPackage = ( {
|
||||||
packageId,
|
packageId,
|
||||||
className,
|
className = '',
|
||||||
noResultsMessage,
|
noResultsMessage,
|
||||||
renderOption,
|
renderOption,
|
||||||
packageData,
|
packageData,
|
||||||
|
@ -65,10 +65,7 @@ export const ShippingRatesControlPackage = ( {
|
||||||
collapse = false,
|
collapse = false,
|
||||||
showItems = false,
|
showItems = false,
|
||||||
}: PackageProps ): ReactElement => {
|
}: PackageProps ): ReactElement => {
|
||||||
const { selectShippingRate, selectedShippingRate } = useSelectShippingRate(
|
const { selectShippingRate } = useSelectShippingRate();
|
||||||
packageId,
|
|
||||||
packageData.shipping_rates
|
|
||||||
);
|
|
||||||
|
|
||||||
const header = (
|
const header = (
|
||||||
<>
|
<>
|
||||||
|
@ -117,8 +114,12 @@ export const ShippingRatesControlPackage = ( {
|
||||||
className={ className }
|
className={ className }
|
||||||
noResultsMessage={ noResultsMessage }
|
noResultsMessage={ noResultsMessage }
|
||||||
rates={ packageData.shipping_rates }
|
rates={ packageData.shipping_rates }
|
||||||
onSelectRate={ selectShippingRate }
|
onSelectRate={ ( newShippingRateId ) =>
|
||||||
selected={ selectedShippingRate }
|
selectShippingRate( newShippingRateId, packageId )
|
||||||
|
}
|
||||||
|
selectedRate={ packageData.shipping_rates.find(
|
||||||
|
( rate ) => rate.selected
|
||||||
|
) }
|
||||||
renderOption={ renderOption }
|
renderOption={ renderOption }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
|
import { useState, useEffect } from '@wordpress/element';
|
||||||
import RadioControl, {
|
import RadioControl, {
|
||||||
RadioControlOptionLayout,
|
RadioControlOptionLayout,
|
||||||
} from '@woocommerce/base-components/radio-control';
|
} from '@woocommerce/base-components/radio-control';
|
||||||
import type { PackageRateOption } from '@woocommerce/type-defs/shipping';
|
import type { PackageRateOption } from '@woocommerce/type-defs/shipping';
|
||||||
import type { ReactElement } from 'react';
|
|
||||||
import type { CartShippingPackageShippingRate } from '@woocommerce/type-defs/cart';
|
import type { CartShippingPackageShippingRate } from '@woocommerce/type-defs/cart';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,18 +20,30 @@ interface PackageRates {
|
||||||
option: CartShippingPackageShippingRate
|
option: CartShippingPackageShippingRate
|
||||||
) => PackageRateOption;
|
) => PackageRateOption;
|
||||||
className?: string;
|
className?: string;
|
||||||
noResultsMessage: ReactElement;
|
noResultsMessage: JSX.Element;
|
||||||
selected?: string;
|
selectedRate: CartShippingPackageShippingRate | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PackageRates = ( {
|
const PackageRates = ( {
|
||||||
className,
|
className = '',
|
||||||
noResultsMessage,
|
noResultsMessage,
|
||||||
onSelectRate,
|
onSelectRate,
|
||||||
rates,
|
rates,
|
||||||
renderOption = renderPackageRateOption,
|
renderOption = renderPackageRateOption,
|
||||||
selected,
|
selectedRate,
|
||||||
}: PackageRates ): ReactElement => {
|
}: PackageRates ): JSX.Element => {
|
||||||
|
const selectedRateId = selectedRate?.rate_id || '';
|
||||||
|
|
||||||
|
// Store selected rate ID in local state so shipping rates changes are shown in the UI instantly.
|
||||||
|
const [ selectedOption, setSelectedOption ] = useState( selectedRateId );
|
||||||
|
|
||||||
|
// Update the selected option if cart state changes in the data stores.
|
||||||
|
useEffect( () => {
|
||||||
|
if ( selectedRateId ) {
|
||||||
|
setSelectedOption( selectedRateId );
|
||||||
|
}
|
||||||
|
}, [ selectedRateId ] );
|
||||||
|
|
||||||
if ( rates.length === 0 ) {
|
if ( rates.length === 0 ) {
|
||||||
return noResultsMessage;
|
return noResultsMessage;
|
||||||
}
|
}
|
||||||
|
@ -40,10 +52,11 @@ const PackageRates = ( {
|
||||||
return (
|
return (
|
||||||
<RadioControl
|
<RadioControl
|
||||||
className={ className }
|
className={ className }
|
||||||
onChange={ ( selectedRateId: string ) => {
|
onChange={ ( value: string ) => {
|
||||||
onSelectRate( selectedRateId );
|
setSelectedOption( value );
|
||||||
|
onSelectRate( value );
|
||||||
} }
|
} }
|
||||||
selected={ selected }
|
selected={ selectedOption }
|
||||||
options={ rates.map( renderOption ) }
|
options={ rates.map( renderOption ) }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
/**
|
|
||||||
* External dependencies
|
|
||||||
*/
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import { withInstanceId } from '@wordpress/compose';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal dependencies
|
|
||||||
*/
|
|
||||||
import RadioControlOption from './option';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
const RadioControl = ( {
|
|
||||||
className = '',
|
|
||||||
instanceId,
|
|
||||||
id,
|
|
||||||
selected,
|
|
||||||
onChange = () => {},
|
|
||||||
options = [],
|
|
||||||
} ) => {
|
|
||||||
const radioControlId = id || instanceId;
|
|
||||||
|
|
||||||
return (
|
|
||||||
options.length && (
|
|
||||||
<div
|
|
||||||
className={ classnames(
|
|
||||||
'wc-block-components-radio-control',
|
|
||||||
className
|
|
||||||
) }
|
|
||||||
>
|
|
||||||
{ options.map( ( option ) => (
|
|
||||||
<RadioControlOption
|
|
||||||
key={ `${ radioControlId }-${ option.value }` }
|
|
||||||
name={ `radio-control-${ radioControlId }` }
|
|
||||||
checked={ option.value === selected }
|
|
||||||
option={ option }
|
|
||||||
onChange={ ( value ) => {
|
|
||||||
onChange( value );
|
|
||||||
if ( typeof option.onChange === 'function' ) {
|
|
||||||
option.onChange( value );
|
|
||||||
}
|
|
||||||
} }
|
|
||||||
/>
|
|
||||||
) ) }
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withInstanceId( RadioControl );
|
|
||||||
export { RadioControlOption };
|
|
||||||
export { default as RadioControlOptionLayout } from './option-layout';
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import { useInstanceId } from '@wordpress/compose';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import RadioControlOption from './option';
|
||||||
|
import type { RadioControlProps } from './types';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
const RadioControl = ( {
|
||||||
|
className = '',
|
||||||
|
id,
|
||||||
|
selected,
|
||||||
|
onChange = () => void 0,
|
||||||
|
options = [],
|
||||||
|
}: RadioControlProps ): JSX.Element | null => {
|
||||||
|
const instanceId = useInstanceId( RadioControl );
|
||||||
|
const radioControlId = id || instanceId;
|
||||||
|
|
||||||
|
if ( ! options.length ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={ classnames(
|
||||||
|
'wc-block-components-radio-control',
|
||||||
|
className
|
||||||
|
) }
|
||||||
|
>
|
||||||
|
{ options.map( ( option ) => (
|
||||||
|
<RadioControlOption
|
||||||
|
key={ `${ radioControlId }-${ option.value }` }
|
||||||
|
name={ `radio-control-${ radioControlId }` }
|
||||||
|
checked={ option.value === selected }
|
||||||
|
option={ option }
|
||||||
|
onChange={ ( value: string ) => {
|
||||||
|
onChange( value );
|
||||||
|
if ( typeof option.onChange === 'function' ) {
|
||||||
|
option.onChange( value );
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
/>
|
||||||
|
) ) }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RadioControl;
|
||||||
|
export { default as RadioControlOption } from './option';
|
||||||
|
export { default as RadioControlOptionLayout } from './option-layout';
|
|
@ -1,8 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import type { ReactElement } from 'react';
|
import type { RadioControlOptionLayout } from './types';
|
||||||
import type { PackageRateOption } from '@woocommerce/type-defs/shipping';
|
|
||||||
|
|
||||||
const OptionLayout = ( {
|
const OptionLayout = ( {
|
||||||
label,
|
label,
|
||||||
|
@ -10,7 +9,7 @@ const OptionLayout = ( {
|
||||||
description,
|
description,
|
||||||
secondaryDescription,
|
secondaryDescription,
|
||||||
id,
|
id,
|
||||||
}: Partial< PackageRateOption > ): ReactElement => {
|
}: RadioControlOptionLayout ): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div className="wc-block-components-radio-control__option-layout">
|
<div className="wc-block-components-radio-control__option-layout">
|
||||||
<div className="wc-block-components-radio-control__label-group">
|
<div className="wc-block-components-radio-control__label-group">
|
||||||
|
|
|
@ -7,8 +7,14 @@ import classnames from 'classnames';
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import OptionLayout from './option-layout';
|
import OptionLayout from './option-layout';
|
||||||
|
import type { RadioControlOptionProps } from './types';
|
||||||
|
|
||||||
const Option = ( { checked, name, onChange, option } ) => {
|
const Option = ( {
|
||||||
|
checked,
|
||||||
|
name,
|
||||||
|
onChange,
|
||||||
|
option,
|
||||||
|
}: RadioControlOptionProps ): JSX.Element => {
|
||||||
const {
|
const {
|
||||||
value,
|
value,
|
||||||
label,
|
label,
|
||||||
|
@ -16,7 +22,8 @@ const Option = ( { checked, name, onChange, option } ) => {
|
||||||
secondaryLabel,
|
secondaryLabel,
|
||||||
secondaryDescription,
|
secondaryDescription,
|
||||||
} = option;
|
} = option;
|
||||||
const onChangeValue = ( event ) => onChange( event.target.value );
|
const onChangeValue = ( event: React.ChangeEvent< HTMLInputElement > ) =>
|
||||||
|
onChange( event.target.value );
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import type { ReactElement } from 'react';
|
||||||
|
|
||||||
|
export interface RadioControlProps {
|
||||||
|
// Class name for control.
|
||||||
|
className?: string;
|
||||||
|
// ID for the control.
|
||||||
|
id?: string;
|
||||||
|
// The selected option. This is a controlled component.
|
||||||
|
selected: string;
|
||||||
|
// Fired when an option is changed.
|
||||||
|
onChange: ( value: string ) => void;
|
||||||
|
// List of radio control options.
|
||||||
|
options: RadioControlOption[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RadioControlOptionProps {
|
||||||
|
checked: boolean;
|
||||||
|
name?: string;
|
||||||
|
onChange: ( value: string ) => void;
|
||||||
|
option: RadioControlOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RadioControlOptionContent {
|
||||||
|
label: string;
|
||||||
|
description?: string | ReactElement | undefined;
|
||||||
|
secondaryLabel?: string | ReactElement | undefined;
|
||||||
|
secondaryDescription?: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RadioControlOption extends RadioControlOptionContent {
|
||||||
|
value: string;
|
||||||
|
onChange?: ( value: string ) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RadioControlOptionLayout extends RadioControlOptionContent {
|
||||||
|
id?: string;
|
||||||
|
}
|
|
@ -1,2 +1 @@
|
||||||
export * from './use-select-shipping-rate';
|
export * from './use-select-shipping-rate';
|
||||||
export * from './use-select-shipping-rates';
|
|
||||||
|
|
|
@ -1,81 +1,70 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { useState, useEffect, useRef, useCallback } from '@wordpress/element';
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
import isShallowEqual from '@wordpress/is-shallow-equal';
|
import { useCallback } from '@wordpress/element';
|
||||||
import { CartShippingPackageShippingRate } from '@woocommerce/type-defs/cart';
|
import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data';
|
||||||
|
import { useThrowError } from '@woocommerce/base-hooks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { useSelectShippingRates } from './use-select-shipping-rates';
|
|
||||||
import { useStoreEvents } from '../use-store-events';
|
import { useStoreEvents } from '../use-store-events';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selected rates are derived by looping over the shipping rates.
|
* This is a custom hook for selecting shipping rates for a shipping package.
|
||||||
*
|
*
|
||||||
* @param {Array} shippingRates Array of shipping rates.
|
|
||||||
* @return {string} Selected rate id.
|
|
||||||
*/
|
|
||||||
// This will find the selected rate ID in an array of shipping rates.
|
|
||||||
const deriveSelectedRateId = (
|
|
||||||
shippingRates: CartShippingPackageShippingRate[]
|
|
||||||
) => shippingRates.find( ( rate ) => rate.selected )?.rate_id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a custom hook for tracking selected shipping rates for a package and selecting a rate. State is used so
|
|
||||||
* changes are reflected in the UI instantly.
|
|
||||||
*
|
|
||||||
* @param {string} packageId Package ID to select rates for.
|
|
||||||
* @param {Array} shippingRates an array of packages with shipping rates.
|
|
||||||
* @return {Object} This hook will return an object with these properties:
|
* @return {Object} This hook will return an object with these properties:
|
||||||
* - selectShippingRate: A function that immediately returns the selected rate and dispatches an action generator.
|
* - selectShippingRate: A function that immediately returns the selected rate and dispatches an action generator.
|
||||||
* - selectedShippingRate: The selected rate id.
|
|
||||||
* - isSelectingRate: True when rates are being resolved to the API.
|
* - isSelectingRate: True when rates are being resolved to the API.
|
||||||
*/
|
*/
|
||||||
export const useSelectShippingRate = (
|
export const useSelectShippingRate = (): {
|
||||||
packageId: string | number,
|
// Returns a function that accepts a shipping rate ID and a package ID.
|
||||||
shippingRates: CartShippingPackageShippingRate[]
|
selectShippingRate: (
|
||||||
): {
|
newShippingRateId: string,
|
||||||
selectShippingRate: ( newShippingRateId: string ) => unknown;
|
packageId: string | number
|
||||||
selectedShippingRate: string | undefined;
|
) => unknown;
|
||||||
|
// True when a rate is currently being selected and persisted to the server.
|
||||||
isSelectingRate: boolean;
|
isSelectingRate: boolean;
|
||||||
} => {
|
} => {
|
||||||
|
const throwError = useThrowError();
|
||||||
const { dispatchCheckoutEvent } = useStoreEvents();
|
const { dispatchCheckoutEvent } = useStoreEvents();
|
||||||
|
|
||||||
// Rates are selected via the shipping data context provider.
|
const { selectShippingRate: dispatchSelectShippingRate } = ( useDispatch(
|
||||||
const { selectShippingRate, isSelectingRate } = useSelectShippingRates();
|
storeKey
|
||||||
|
) as {
|
||||||
|
selectShippingRate: unknown;
|
||||||
|
} ) as {
|
||||||
|
selectShippingRate: (
|
||||||
|
newShippingRateId: string,
|
||||||
|
packageId: string | number
|
||||||
|
) => Promise< unknown >;
|
||||||
|
};
|
||||||
|
|
||||||
// Selected rates are stored in state. This allows shipping rates changes to be shown in the UI instantly.
|
// Selects a shipping rate, fires an event, and catch any errors.
|
||||||
// Defaults to the currently selected rate_id.
|
const selectShippingRate = useCallback(
|
||||||
const [ selectedShippingRate, setSelectedShippingRate ] = useState( () =>
|
( newShippingRateId, packageId ) => {
|
||||||
deriveSelectedRateId( shippingRates )
|
dispatchSelectShippingRate( newShippingRateId, packageId )
|
||||||
);
|
.then( () => {
|
||||||
|
dispatchCheckoutEvent( 'set-selected-shipping-rate', {
|
||||||
// This ref is used to track when changes come in via the props. When the incoming shipping rates change, update our local state if there are changes to selected methods.
|
shippingRateId: newShippingRateId,
|
||||||
const currentShippingRates = useRef( shippingRates );
|
} );
|
||||||
useEffect( () => {
|
} )
|
||||||
if ( ! isShallowEqual( currentShippingRates.current, shippingRates ) ) {
|
.catch( ( error ) => {
|
||||||
currentShippingRates.current = shippingRates;
|
// Throw an error because an error when selecting a rate is problematic.
|
||||||
setSelectedShippingRate( deriveSelectedRateId( shippingRates ) );
|
throwError( error );
|
||||||
}
|
} );
|
||||||
}, [ shippingRates ] );
|
|
||||||
|
|
||||||
// Sets a rate for a package in state (so changes are shown right away to consumers of the hook) and in the stores.
|
|
||||||
const setPackageRateId = useCallback(
|
|
||||||
( newShippingRateId ) => {
|
|
||||||
setSelectedShippingRate( newShippingRateId );
|
|
||||||
selectShippingRate( newShippingRateId, packageId );
|
|
||||||
dispatchCheckoutEvent( 'set-selected-shipping-rate', {
|
|
||||||
shippingRateId: newShippingRateId,
|
|
||||||
} );
|
|
||||||
},
|
},
|
||||||
[ packageId, selectShippingRate, dispatchCheckoutEvent ]
|
[ dispatchSelectShippingRate, dispatchCheckoutEvent, throwError ]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// See if rates are being selected.
|
||||||
|
const isSelectingRate = useSelect< boolean >( ( select ) => {
|
||||||
|
return select( storeKey ).isShippingRateBeingSelected();
|
||||||
|
}, [] );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectShippingRate: setPackageRateId,
|
selectShippingRate,
|
||||||
selectedShippingRate,
|
|
||||||
isSelectingRate,
|
isSelectingRate,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
/**
|
|
||||||
* External dependencies
|
|
||||||
*/
|
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
|
||||||
import { useCallback } from '@wordpress/element';
|
|
||||||
import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data';
|
|
||||||
import { useThrowError } from '@woocommerce/base-hooks';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a custom hook for selecting shipping rates
|
|
||||||
*
|
|
||||||
* @return {Object} This hook will return an object with these properties:
|
|
||||||
* - selectShippingRate: A function that immediately returns the selected rate and dispatches an action generator.
|
|
||||||
* - isSelectingRate: True when rates are being resolved to the API.
|
|
||||||
*/
|
|
||||||
export const useSelectShippingRates = (): {
|
|
||||||
selectShippingRate: (
|
|
||||||
newShippingRateId: string,
|
|
||||||
packageId: string | number
|
|
||||||
) => unknown;
|
|
||||||
isSelectingRate: boolean;
|
|
||||||
} => {
|
|
||||||
const throwError = useThrowError();
|
|
||||||
const { selectShippingRate } = ( useDispatch( storeKey ) as {
|
|
||||||
selectShippingRate: unknown;
|
|
||||||
} ) as {
|
|
||||||
selectShippingRate: (
|
|
||||||
newShippingRateId: string,
|
|
||||||
packageId: string | number
|
|
||||||
) => Promise< unknown >;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Sets a rate for a package in state (so changes are shown right away to consumers of the hook) and in the stores.
|
|
||||||
const setRate = useCallback(
|
|
||||||
( newShippingRateId, packageId ) => {
|
|
||||||
selectShippingRate( newShippingRateId, packageId ).catch(
|
|
||||||
( error ) => {
|
|
||||||
// we throw this error because an error on selecting a rate is problematic.
|
|
||||||
throwError( error );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[ throwError, selectShippingRate ]
|
|
||||||
);
|
|
||||||
|
|
||||||
// See if rates are being selected.
|
|
||||||
const isSelectingRate = useSelect< boolean >( ( select ) => {
|
|
||||||
return select( storeKey ).isShippingRateBeingSelected();
|
|
||||||
}, [] );
|
|
||||||
|
|
||||||
return {
|
|
||||||
selectShippingRate: setRate,
|
|
||||||
isSelectingRate,
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -27,7 +27,7 @@ import {
|
||||||
import { useCheckoutContext } from '../checkout-state';
|
import { useCheckoutContext } from '../checkout-state';
|
||||||
import { useCustomerDataContext } from '../customer';
|
import { useCustomerDataContext } from '../customer';
|
||||||
import { useStoreCart } from '../../../hooks/cart/use-store-cart';
|
import { useStoreCart } from '../../../hooks/cart/use-store-cart';
|
||||||
import { useSelectShippingRates } from '../../../hooks/shipping/use-select-shipping-rates';
|
import { useSelectShippingRate } from '../../../hooks/shipping/use-select-shipping-rate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('@woocommerce/type-defs/contexts').ShippingDataContext} ShippingDataContext
|
* @typedef {import('@woocommerce/type-defs/contexts').ShippingDataContext} ShippingDataContext
|
||||||
|
@ -60,7 +60,7 @@ export const ShippingDataProvider = ( { children } ) => {
|
||||||
shippingRatesLoading,
|
shippingRatesLoading,
|
||||||
cartErrors,
|
cartErrors,
|
||||||
} = useStoreCart();
|
} = useStoreCart();
|
||||||
const { selectShippingRate, isSelectingRate } = useSelectShippingRates();
|
const { selectShippingRate, isSelectingRate } = useSelectShippingRate();
|
||||||
const [ shippingErrorStatus, dispatchErrorStatus ] = useReducer(
|
const [ shippingErrorStatus, dispatchErrorStatus ] = useReducer(
|
||||||
errorStatusReducer,
|
errorStatusReducer,
|
||||||
NONE
|
NONE
|
||||||
|
|
Loading…
Reference in New Issue