woocommerce/plugins/woocommerce-blocks/assets/js/base/hooks/cart/use-store-cart-item-quantit...

123 lines
3.6 KiB
TypeScript
Raw Normal View History

/**
* External dependencies
*/
improve responsiveness when setting cart item quantities (https://github.com/woocommerce/woocommerce-blocks/pull/1864) * rework the quantity change generator action so the UI updates quick: - work in progress - still need to figure out how to debounce API call - add new action for updating quantity for an item - don't set cart item as pending while quantity is updating - this leaves QuantitySelector enabled so user can click more/less - use receiveCartItemQuantity to update quantity in UI before sending request * debounce line item quantity first cut: - use local state for quantity, so ui allows multiple clicks up/down - debounce store updates (and server/API call) * correct comment on cart item quantity reducer * remove recieveCartItemQuantity - no longer needed * remove delegation for deleted RECEIVE_CART_ITEM_QUANTITY * only update quantity in component sideffect if it has changed: - reduces unnecessary renders * factor out debounced quantity update into cartItem hook (hat tip @senadir) * use quantity from store, instead of passing in to hook + + fix latent bug in useStoreCartItem - the cartItem value is now object: - was previously single-item array - (note no client code is using this at present) * tidy/refactor cart item hook - separate dispatch from select * remove dud reset of item pending flag (came back in rebase) * add quantity to StoreCartItem hook return value typedef * fix js error when adding cart block in editor – cartItem not found * fix typedef * fix logic for debouncing * don’t update quantity on server unnecessarily Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
2020-03-09 02:09:47 +00:00
import { useSelect, useDispatch } from '@wordpress/data';
import { useState, useEffect } from '@wordpress/element';
import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data';
improve responsiveness when setting cart item quantities (https://github.com/woocommerce/woocommerce-blocks/pull/1864) * rework the quantity change generator action so the UI updates quick: - work in progress - still need to figure out how to debounce API call - add new action for updating quantity for an item - don't set cart item as pending while quantity is updating - this leaves QuantitySelector enabled so user can click more/less - use receiveCartItemQuantity to update quantity in UI before sending request * debounce line item quantity first cut: - use local state for quantity, so ui allows multiple clicks up/down - debounce store updates (and server/API call) * correct comment on cart item quantity reducer * remove recieveCartItemQuantity - no longer needed * remove delegation for deleted RECEIVE_CART_ITEM_QUANTITY * only update quantity in component sideffect if it has changed: - reduces unnecessary renders * factor out debounced quantity update into cartItem hook (hat tip @senadir) * use quantity from store, instead of passing in to hook + + fix latent bug in useStoreCartItem - the cartItem value is now object: - was previously single-item array - (note no client code is using this at present) * tidy/refactor cart item hook - separate dispatch from select * remove dud reset of item pending flag (came back in rebase) * add quantity to StoreCartItem hook return value typedef * fix js error when adding cart block in editor – cartItem not found * fix typedef * fix logic for debouncing * don’t update quantity on server unnecessarily Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
2020-03-09 02:09:47 +00:00
import { useDebounce } from 'use-debounce';
import { useCheckoutContext } from '@woocommerce/base-context';
import { triggerFragmentRefresh } from '@woocommerce/base-utils';
import type { CartItem, StoreCartItemQuantity } from '@woocommerce/types';
/**
* Internal dependencies
*/
import { useStoreCart } from './use-store-cart';
import { usePrevious } from '../use-previous';
/**
* This is a custom hook for loading the Store API /cart/ endpoint and actions for removing or changing item quantity.
*
* @see https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/trunk/src/RestApi/StoreApi
*
* @param {CartItem} cartItem The cartItem to get quantity info from and will have quantity updated on.
* @return {StoreCartItemQuantity} An object exposing data and actions relating to cart items.
*/
export const useStoreCartItemQuantity = (
cartItem: CartItem
): StoreCartItemQuantity => {
const { key: cartItemKey = '', quantity: cartItemQuantity = 1 } = cartItem;
const { cartErrors } = useStoreCart();
const { dispatchActions } = useCheckoutContext();
// Store quantity in hook state. This is used to keep the UI updated while server request is updated.
const [ quantity, setQuantity ] = useState< number >( cartItemQuantity );
const [ debouncedQuantity ] = useDebounce< number >( quantity, 400 );
const previousDebouncedQuantity = usePrevious( debouncedQuantity );
const { removeItemFromCart, changeCartItemQuantity } = useDispatch(
storeKey
);
// Track when things are already pending updates.
const isPending = useSelect(
improve responsiveness when setting cart item quantities (https://github.com/woocommerce/woocommerce-blocks/pull/1864) * rework the quantity change generator action so the UI updates quick: - work in progress - still need to figure out how to debounce API call - add new action for updating quantity for an item - don't set cart item as pending while quantity is updating - this leaves QuantitySelector enabled so user can click more/less - use receiveCartItemQuantity to update quantity in UI before sending request * debounce line item quantity first cut: - use local state for quantity, so ui allows multiple clicks up/down - debounce store updates (and server/API call) * correct comment on cart item quantity reducer * remove recieveCartItemQuantity - no longer needed * remove delegation for deleted RECEIVE_CART_ITEM_QUANTITY * only update quantity in component sideffect if it has changed: - reduces unnecessary renders * factor out debounced quantity update into cartItem hook (hat tip @senadir) * use quantity from store, instead of passing in to hook + + fix latent bug in useStoreCartItem - the cartItem value is now object: - was previously single-item array - (note no client code is using this at present) * tidy/refactor cart item hook - separate dispatch from select * remove dud reset of item pending flag (came back in rebase) * add quantity to StoreCartItem hook return value typedef * fix js error when adding cart block in editor – cartItem not found * fix typedef * fix logic for debouncing * don’t update quantity on server unnecessarily Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
2020-03-09 02:09:47 +00:00
( select ) => {
if ( ! cartItemKey ) {
return {
quantity: false,
delete: false,
};
}
const store = select( storeKey );
return {
quantity: store.isItemPendingQuantity( cartItemKey ),
delete: store.isItemPendingDelete( cartItemKey ),
};
},
[ cartItemKey ]
);
const previousIsPending = usePrevious( isPending );
const removeItem = () => {
return cartItemKey
? removeItemFromCart( cartItemKey ).then( () => {
triggerFragmentRefresh();
return true;
} )
: Promise.resolve( false );
};
improve responsiveness when setting cart item quantities (https://github.com/woocommerce/woocommerce-blocks/pull/1864) * rework the quantity change generator action so the UI updates quick: - work in progress - still need to figure out how to debounce API call - add new action for updating quantity for an item - don't set cart item as pending while quantity is updating - this leaves QuantitySelector enabled so user can click more/less - use receiveCartItemQuantity to update quantity in UI before sending request * debounce line item quantity first cut: - use local state for quantity, so ui allows multiple clicks up/down - debounce store updates (and server/API call) * correct comment on cart item quantity reducer * remove recieveCartItemQuantity - no longer needed * remove delegation for deleted RECEIVE_CART_ITEM_QUANTITY * only update quantity in component sideffect if it has changed: - reduces unnecessary renders * factor out debounced quantity update into cartItem hook (hat tip @senadir) * use quantity from store, instead of passing in to hook + + fix latent bug in useStoreCartItem - the cartItem value is now object: - was previously single-item array - (note no client code is using this at present) * tidy/refactor cart item hook - separate dispatch from select * remove dud reset of item pending flag (came back in rebase) * add quantity to StoreCartItem hook return value typedef * fix js error when adding cart block in editor – cartItem not found * fix typedef * fix logic for debouncing * don’t update quantity on server unnecessarily Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
2020-03-09 02:09:47 +00:00
// Observe debounced quantity value, fire action to update server on change.
improve responsiveness when setting cart item quantities (https://github.com/woocommerce/woocommerce-blocks/pull/1864) * rework the quantity change generator action so the UI updates quick: - work in progress - still need to figure out how to debounce API call - add new action for updating quantity for an item - don't set cart item as pending while quantity is updating - this leaves QuantitySelector enabled so user can click more/less - use receiveCartItemQuantity to update quantity in UI before sending request * debounce line item quantity first cut: - use local state for quantity, so ui allows multiple clicks up/down - debounce store updates (and server/API call) * correct comment on cart item quantity reducer * remove recieveCartItemQuantity - no longer needed * remove delegation for deleted RECEIVE_CART_ITEM_QUANTITY * only update quantity in component sideffect if it has changed: - reduces unnecessary renders * factor out debounced quantity update into cartItem hook (hat tip @senadir) * use quantity from store, instead of passing in to hook + + fix latent bug in useStoreCartItem - the cartItem value is now object: - was previously single-item array - (note no client code is using this at present) * tidy/refactor cart item hook - separate dispatch from select * remove dud reset of item pending flag (came back in rebase) * add quantity to StoreCartItem hook return value typedef * fix js error when adding cart block in editor – cartItem not found * fix typedef * fix logic for debouncing * don’t update quantity on server unnecessarily Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
2020-03-09 02:09:47 +00:00
useEffect( () => {
if (
cartItemKey &&
Number.isFinite( previousDebouncedQuantity ) &&
previousDebouncedQuantity !== debouncedQuantity
) {
changeCartItemQuantity( cartItemKey, debouncedQuantity ).then(
triggerFragmentRefresh
);
}
}, [
cartItemKey,
changeCartItemQuantity,
debouncedQuantity,
previousDebouncedQuantity,
] );
useEffect( () => {
if ( typeof previousIsPending === 'undefined' ) {
return;
}
if ( previousIsPending.quantity !== isPending.quantity ) {
if ( isPending.quantity ) {
dispatchActions.incrementCalculating();
} else {
dispatchActions.decrementCalculating();
}
}
if ( previousIsPending.delete !== isPending.delete ) {
if ( isPending.delete ) {
dispatchActions.incrementCalculating();
} else {
dispatchActions.decrementCalculating();
}
}
return () => {
if ( isPending.quantity ) {
dispatchActions.decrementCalculating();
}
if ( isPending.delete ) {
dispatchActions.decrementCalculating();
}
};
}, [ dispatchActions, isPending, previousIsPending ] );
return {
isPendingDelete: isPending.delete,
improve responsiveness when setting cart item quantities (https://github.com/woocommerce/woocommerce-blocks/pull/1864) * rework the quantity change generator action so the UI updates quick: - work in progress - still need to figure out how to debounce API call - add new action for updating quantity for an item - don't set cart item as pending while quantity is updating - this leaves QuantitySelector enabled so user can click more/less - use receiveCartItemQuantity to update quantity in UI before sending request * debounce line item quantity first cut: - use local state for quantity, so ui allows multiple clicks up/down - debounce store updates (and server/API call) * correct comment on cart item quantity reducer * remove recieveCartItemQuantity - no longer needed * remove delegation for deleted RECEIVE_CART_ITEM_QUANTITY * only update quantity in component sideffect if it has changed: - reduces unnecessary renders * factor out debounced quantity update into cartItem hook (hat tip @senadir) * use quantity from store, instead of passing in to hook + + fix latent bug in useStoreCartItem - the cartItem value is now object: - was previously single-item array - (note no client code is using this at present) * tidy/refactor cart item hook - separate dispatch from select * remove dud reset of item pending flag (came back in rebase) * add quantity to StoreCartItem hook return value typedef * fix js error when adding cart block in editor – cartItem not found * fix typedef * fix logic for debouncing * don’t update quantity on server unnecessarily Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
2020-03-09 02:09:47 +00:00
quantity,
setItemQuantity: setQuantity,
improve responsiveness when setting cart item quantities (https://github.com/woocommerce/woocommerce-blocks/pull/1864) * rework the quantity change generator action so the UI updates quick: - work in progress - still need to figure out how to debounce API call - add new action for updating quantity for an item - don't set cart item as pending while quantity is updating - this leaves QuantitySelector enabled so user can click more/less - use receiveCartItemQuantity to update quantity in UI before sending request * debounce line item quantity first cut: - use local state for quantity, so ui allows multiple clicks up/down - debounce store updates (and server/API call) * correct comment on cart item quantity reducer * remove recieveCartItemQuantity - no longer needed * remove delegation for deleted RECEIVE_CART_ITEM_QUANTITY * only update quantity in component sideffect if it has changed: - reduces unnecessary renders * factor out debounced quantity update into cartItem hook (hat tip @senadir) * use quantity from store, instead of passing in to hook + + fix latent bug in useStoreCartItem - the cartItem value is now object: - was previously single-item array - (note no client code is using this at present) * tidy/refactor cart item hook - separate dispatch from select * remove dud reset of item pending flag (came back in rebase) * add quantity to StoreCartItem hook return value typedef * fix js error when adding cart block in editor – cartItem not found * fix typedef * fix logic for debouncing * don’t update quantity on server unnecessarily Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
2020-03-09 02:09:47 +00:00
removeItem,
cartItemQuantityErrors: cartErrors,
};
};