From 41c97204d0f857be57e48e614a18c29d95cdb4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Magalh=C3=A3es?= Date: Thu, 30 Nov 2023 19:12:33 -0300 Subject: [PATCH 1/2] fix: fixing on seller wrapper when there is no seller available refactor: refactoring and adding some custom hooks --- CHANGELOG.md | 4 + react/SellerWrapper.tsx | 91 +------------------ .../SellerWrapper/SellerWrapper.tsx | 30 ++++++ react/hooks/useSelectSeller.ts | 67 ++++++++++++++ react/hooks/{useSeller.tsx => useSeller.ts} | 0 5 files changed, 102 insertions(+), 90 deletions(-) create mode 100644 react/components/SellerWrapper/SellerWrapper.tsx create mode 100644 react/hooks/useSelectSeller.ts rename react/hooks/{useSeller.tsx => useSeller.ts} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index b845fd62..8a821608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Fixed + +- Fixing on seller wrapper when there is no seller available + ## [1.28.1] - 2023-11-06 ### Fixed diff --git a/react/SellerWrapper.tsx b/react/SellerWrapper.tsx index b74483f0..3363ae45 100644 --- a/react/SellerWrapper.tsx +++ b/react/SellerWrapper.tsx @@ -1,92 +1,3 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react' -import { useProduct, useProductDispatch } from 'vtex.product-context' -import { useCssHandles } from 'vtex.css-handles' -import type { Item } from 'vtex.product-context/react/ProductTypes' - -import useSeller from './hooks/useSeller' - -const CSS_HANDLES = ['sellerWrapper', 'loadingSeller'] -const SELECT_ITEM_EVENT = 'SET_SELECTED_ITEM' - -type SellerWrapperProps = { - children: React.ReactNode -} - -const SellerWrapper = ({ children }: SellerWrapperProps) => { - const { seller } = useSeller() - const dispatch = useProductDispatch() - const { selectedItem, product } = useProduct() ?? {} - const latestItem = useRef((null as unknown) as Item) - const handles = useCssHandles(CSS_HANDLES) - const [loadingSeller, setLoadingSeller] = useState(true) - - const addSellerDefaultToItem = useCallback( - itemSeller => ({ - ...itemSeller, - sellerDefault: seller?.includes(itemSeller.sellerId), - }), - [seller] - ) - - useEffect(() => { - const shouldDispatchSelectItem = - !!seller && !!product && !!selectedItem && !!dispatch - - if (!shouldDispatchSelectItem) return - const newCurrentSelectedItem = - product?.items?.find(item => - item.sellers?.find( - itemSeller => - seller?.includes(itemSeller.sellerId) && - itemSeller.commertialOffer.AvailableQuantity > 0 - ) - ) ?? ({} as Item) - - if (!newCurrentSelectedItem) { - return - } - - const { sellers } = newCurrentSelectedItem - const selectedItemWithSeller = { - ...newCurrentSelectedItem, - sellers: sellers.map(addSellerDefaultToItem), - } - - if ( - JSON.stringify(latestItem.current) === - JSON.stringify(selectedItemWithSeller) - ) { - return - } - - dispatch?.({ - type: SELECT_ITEM_EVENT, - args: { - item: selectedItemWithSeller, - }, - }) - - setLoadingSeller(false) - - latestItem.current = selectedItemWithSeller - }, [ - seller, - product, - selectedItem, - dispatch, - addSellerDefaultToItem, - latestItem, - ]) - - return ( -
- {children} -
- ) -} +import SellerWrapper from './components/SellerWrapper/SellerWrapper' export default SellerWrapper diff --git a/react/components/SellerWrapper/SellerWrapper.tsx b/react/components/SellerWrapper/SellerWrapper.tsx new file mode 100644 index 00000000..825664b5 --- /dev/null +++ b/react/components/SellerWrapper/SellerWrapper.tsx @@ -0,0 +1,30 @@ +import React, { useEffect } from 'react' +import { useCssHandles } from 'vtex.css-handles' +import { useProduct } from 'vtex.product-context' + +import { useSelectSeller } from '../../hooks/useSelectSeller' + +type SellerWrapperProps = { + children: React.ReactNode +} + +const CSS_HANDLES = ['sellerWrapper', 'sellerWrapperNoSeller'] + +const SellerWrapper = ({ children }: SellerWrapperProps) => { + const handles = useCssHandles(CSS_HANDLES) + const { currentSelectedItem, selectSeller } = useSelectSeller() + + const { selectedItem } = useProduct() ?? {} + + useEffect(() => { + selectSeller() + }, [selectedItem, selectSeller]) + + const className = currentSelectedItem + ? `${handles.sellerWrapper}` + : `${handles.sellerWrapper} ${handles.sellerWrapperNoSeller}` + + return
{children}
+} + +export default SellerWrapper diff --git a/react/hooks/useSelectSeller.ts b/react/hooks/useSelectSeller.ts new file mode 100644 index 00000000..f6c73878 --- /dev/null +++ b/react/hooks/useSelectSeller.ts @@ -0,0 +1,67 @@ +import { useProduct, useProductDispatch } from 'vtex.product-context' +import { useCallback, useMemo, useRef, useState } from 'react' +import type { Item } from 'vtex.product-context/react/ProductTypes' + +import useSeller from './useSeller' + +const SELECT_ITEM_EVENT = 'SET_SELECTED_ITEM' + +export const useSelectSeller = () => { + const { seller } = useSeller() + const { product } = useProduct() ?? {} + const latestItem = useRef((null as unknown) as Item) + const [loading, setLoading] = useState(true) + const productDispatch = useProductDispatch() + + const addSellerDefaultToItem = useCallback( + itemSeller => ({ + ...itemSeller, + sellerDefault: seller?.includes(itemSeller.sellerId), + }), + [seller] + ) + + const currentSelectedItem = useMemo( + () => + product?.items?.find(item => + item.sellers?.find( + itemSeller => + seller?.includes(itemSeller.sellerId) && + itemSeller.commertialOffer.AvailableQuantity > 0 + ) + ) ?? null, + + [seller, product] + ) + + const selectSeller = () => { + if (!currentSelectedItem) { + return + } + + setLoading(true) + const { sellers } = (currentSelectedItem as unknown) as Item + const selectedItemWithSeller = { + ...((currentSelectedItem as unknown) as Item), + sellers: sellers.map(addSellerDefaultToItem), + } + + if ( + JSON.stringify(latestItem.current) === + JSON.stringify(selectedItemWithSeller) + ) { + return + } + + productDispatch?.({ + type: SELECT_ITEM_EVENT, + args: { + item: selectedItemWithSeller, + }, + }) + setLoading(false) + latestItem.current = selectedItemWithSeller + } + + return { loading, seller, currentSelectedItem, selectSeller } +} diff --git a/react/hooks/useSeller.tsx b/react/hooks/useSeller.ts similarity index 100% rename from react/hooks/useSeller.tsx rename to react/hooks/useSeller.ts From 09cd9e99c26e0acd6c1fd54bd927620c62a9f21b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Magalh=C3=A3es?= Date: Mon, 11 Dec 2023 15:19:07 -0300 Subject: [PATCH 2/2] added: added a dependency on useEffect call and selectedSeller --- react/components/SellerWrapper/SellerWrapper.tsx | 2 +- react/hooks/useSelectSeller.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/react/components/SellerWrapper/SellerWrapper.tsx b/react/components/SellerWrapper/SellerWrapper.tsx index 825664b5..65d021ab 100644 --- a/react/components/SellerWrapper/SellerWrapper.tsx +++ b/react/components/SellerWrapper/SellerWrapper.tsx @@ -17,7 +17,7 @@ const SellerWrapper = ({ children }: SellerWrapperProps) => { const { selectedItem } = useProduct() ?? {} useEffect(() => { - selectSeller() + selectSeller({ selectedItem }) }, [selectedItem, selectSeller]) const className = currentSelectedItem diff --git a/react/hooks/useSelectSeller.ts b/react/hooks/useSelectSeller.ts index f6c73878..9b1a57ac 100644 --- a/react/hooks/useSelectSeller.ts +++ b/react/hooks/useSelectSeller.ts @@ -34,11 +34,16 @@ export const useSelectSeller = () => { [seller, product] ) - const selectSeller = () => { - if (!currentSelectedItem) { + const selectSeller = ({ + selectedItem, + }: { + selectedItem: Item | null | undefined + }) => { + if (!currentSelectedItem || !selectedItem) { return } + // just to keep the dependency setLoading(true) const { sellers } = (currentSelectedItem as unknown) as Item const selectedItemWithSeller = {