Skip to content

Commit

Permalink
perf: Improve network requests
Browse files Browse the repository at this point in the history
  • Loading branch information
acasazza committed May 6, 2022
1 parent 111c202 commit b4ef18e
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 18 deletions.
18 changes: 15 additions & 3 deletions src/components/AvailabilityContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, {
import availabilityReducer, {
availabilityInitialState,
getAvailability,
getAvailabilityByIds,
} from '#reducers/AvailabilityReducer'
import AvailabilityContext from '#context/AvailabilityContext'
import ItemContext from '#context/ItemContext'
Expand All @@ -16,6 +17,8 @@ import components from '#config/components'
import CommerceLayerContext from '#context/CommerceLayerContext'
import LineItemChildrenContext from '#context/LineItemChildrenContext'
import SkuChildrenContext from '#context/SkuChildrenContext'
import SkuContext from '#context/SkuContext'
import isEqual from 'lodash/isEqual'

const propTypes = components.AvailabilityContainer.propTypes
const displayName = components.AvailabilityContainer.displayName
Expand All @@ -32,6 +35,7 @@ const AvailabilityContainer: FunctionComponent<AvailabilityContainerProps> = (
const { item, skuCode: itemSkuCode, setItem } = useContext(ItemContext)
const { lineItem } = useContext(LineItemChildrenContext)
const { sku } = useContext(SkuChildrenContext)
const { skus } = useContext(SkuContext)
const config = useContext(CommerceLayerContext)
const [state, dispatch] = useReducer(
availabilityReducer,
Expand All @@ -44,7 +48,7 @@ const AvailabilityContainer: FunctionComponent<AvailabilityContainerProps> = (
lineItem?.sku_code ||
sku?.code
useEffect(() => {
if (sCode) {
if (sCode && !skus) {
const available = item[sCode]?.inventory?.available
const quantity = item[sCode]?.inventory?.quantity
const [level] = item[sCode]?.inventory?.levels || [
Expand All @@ -60,21 +64,29 @@ const AvailabilityContainer: FunctionComponent<AvailabilityContainerProps> = (
payload: { ...delivery, quantity: level?.quantity },
})
} else if (config.accessToken && !item?.[sCode]) {
getAvailability({ skuCode: sCode, config, dispatch, setItem })
getAvailability({ skuCode: sCode, config, dispatch, setItem, item })
} else if (!available) {
dispatch({
type: 'setAvailability',
payload: { quantity },
})
}
} else if (skus && config.accessToken) {
const itemKeys = Object.keys(item)
const skuCodes = skus.map((s) => s?.code)
if (!isEqual(skuCodes, itemKeys)) {
const skusIds = skus.map((s) => s.id)
getAvailabilityByIds({ skusIds, config, dispatch, setItem })
}
}

return (): void => {
dispatch({
type: 'setAvailability',
payload: {},
})
}
}, [config.accessToken, item, sCode])
}, [config.accessToken, item, sCode, skus])
return (
<AvailabilityContext.Provider value={{ ...state }}>
{children}
Expand Down
25 changes: 21 additions & 4 deletions src/components/AvailabilityTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React, { useContext, FunctionComponent } from 'react'
import { useContext, FunctionComponent } from 'react'
import AvailabilityContext from '#context/AvailabilityContext'
import Parent from './utils/Parent'
import { isEmpty } from 'lodash'
import components from '#config/components'
import { TimeFormat, FunctionChildren } from '#typings/index'
import { DeliveryLeadTime } from '#reducers/AvailabilityReducer'
import ItemContext from '#context/ItemContext'
import SkuChildrenContext from '#context/SkuChildrenContext'

const propTypes = components.AvailabilityTemplate.propTypes
const defaultProps = components.AvailabilityTemplate
Expand Down Expand Up @@ -33,11 +35,26 @@ const AvailabilityTemplate: FunctionComponent<AvailabilityTemplateProps> = (
children,
...p
} = props
const { min, max, shipping_method, quantity } =
useContext(AvailabilityContext)
let { min, max, shipping_method, quantity } = useContext(AvailabilityContext)
const { item } = useContext(ItemContext)
const { sku } = useContext(SkuChildrenContext)
const text: string[] = []
if (item && sku) {
const code = sku.code as string
const currentItem = item[code]
if (currentItem) {
const [level] = currentItem.inventory?.levels || []
const [delivery] = level?.delivery_lead_times || []
if (delivery) {
min = delivery?.min
max = delivery?.max
shipping_method = delivery?.shipping_method
}
quantity = currentItem.inventory.quantity
}
}
const mn = !isEmpty(min) && timeFormat ? min?.[timeFormat] : ''
const mx = !isEmpty(max) && timeFormat ? max?.[timeFormat] : ''
const text: string[] = []
const shippingMethodPrice =
showShippingMethodPrice && shipping_method?.formatted_price_amount
? `(${shipping_method?.formatted_price_amount})`
Expand Down
6 changes: 2 additions & 4 deletions src/components/ItemContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import itemReducer, {
import { ItemPrices } from '#reducers/ItemReducer'
import components from '#config/components'
import { BFSetStateContainer } from '#typings'
import SkuChildrenContext from '#context/SkuChildrenContext'

const propTypes = components.ItemContainer.propTypes
const displayName = components.ItemContainer.displayName
Expand All @@ -32,9 +31,8 @@ type ItemContainerProps = {
const ItemContainer: React.FunctionComponent<ItemContainerProps> = (props) => {
const { children, skuCode, lineItem } = props
const [state, dispatch] = useReducer(itemReducer, itemInitialState)
const { sku } = useContext(SkuChildrenContext)
useEffect(() => {
const code = skuCode || sku?.code
const code = skuCode
if (code) {
setItemState(code, { type: 'setSkuCode', key: 'skuCode' }, dispatch)
}
Expand All @@ -45,7 +43,7 @@ const ItemContainer: React.FunctionComponent<ItemContainerProps> = (props) => {
dispatch
)
}
}, [sku?.code])
}, [])
const setItems: BFSetStateContainer<Items> = (items) =>
setItemState(items, { type: 'setItems', key: 'items' }, dispatch)
const setItem: BFSetStateContainer<Items> = (item) =>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Price.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { getPricesComponent } from '#utils/getPrices'
import { Price as PriceType } from '@commercelayer/sdk'
import components from '#config/components'
import { FunctionChildren, LoaderType } from '#typings/index'
import SkuChildrenContext from '#context/SkuChildrenContext'

const propTypes = components.Price.propTypes
const defaultProps = components.Price.defaultProps
Expand Down Expand Up @@ -42,8 +43,9 @@ const Price: FunctionComponent<PriceProps> = (props) => {
setSkuCodes,
loader,
} = useContext(PricesContext)
const { sku } = useContext(SkuChildrenContext)
const [skuPrices, setSkuPrices] = useState<PriceType[]>([])
const sCode = pricesSkuCode || skuCode
const sCode = pricesSkuCode || skuCode || (sku?.code as string)
useEffect(() => {
if (!isEmpty(prices) && has(prices, `${sCode}`)) {
setSkuPrices(prices[sCode] as PriceType[])
Expand Down
18 changes: 13 additions & 5 deletions src/components/PricesContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, {
import {
useEffect,
FunctionComponent,
useContext,
useReducer,
ReactNode,
} from 'react'
import getPrices from '#utils/getPrices'
import { isEmpty, indexOf, has } from 'lodash'
import isEmpty from 'lodash/isEmpty'
import has from 'lodash/has'
import indexOf from 'lodash/indexOf'
import CommerceLayerContext from '#context/CommerceLayerContext'
import priceReducer, {
SetSkuCodesPrice,
Expand All @@ -18,7 +20,8 @@ import getCurrentItemKey from '#utils/getCurrentItemKey'
import ItemContext from '#context/ItemContext'
import components from '#config/components'
import { LoaderType } from '#typings'
import SkuChildrenContext from '#context/SkuChildrenContext'
// import SkuChildrenContext from '#context/SkuChildrenContext'
import SkuContext from '#context/SkuContext'

const propTypes = components.PricesContainer.propTypes
const defaultProps = components.PricesContainer.defaultProps
Expand All @@ -42,7 +45,7 @@ const PricesContainer: FunctionComponent<PricesContainerProps> = (props) => {
} = props
const [state, dispatch] = useReducer(priceReducer, priceInitialState)
const config = useContext(CommerceLayerContext)
const { sku } = useContext(SkuChildrenContext)
const { skuCodes } = useContext(SkuContext)
const {
setPrices,
prices,
Expand All @@ -53,14 +56,19 @@ const PricesContainer: FunctionComponent<PricesContainerProps> = (props) => {
if (indexOf(state.skuCodes, skuCode) === -1 && skuCode)
state.skuCodes.push(skuCode)
const sCode =
getCurrentItemKey(currentItem) || sku?.code || skuCode || itemSkuCode || ''
skuCodes && skuCodes?.length > 0
? ''
: getCurrentItemKey(currentItem) || skuCode || itemSkuCode || ''
const setSkuCodes: SetSkuCodesPrice = (skuCodes) => {
dispatch({
type: 'setSkuCodes',
payload: { skuCodes },
})
}
useEffect(() => {
if (state.skuCodes.length === 0 && skuCodes && skuCodes.length > 0) {
setSkuCodes(skuCodes)
}
if (currentItem && has(prices, sCode)) {
dispatch({
type: 'setPrices',
Expand Down
37 changes: 36 additions & 1 deletion src/reducers/AvailabilityReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ type GetAvailability = (args: {
dispatch: Dispatch<AvailabilityAction>
config: CommerceLayerConfig
setItem?: (item: Items) => void
item?: Items
}) => void

export const getAvailability: GetAvailability = async ({
skuCode,
dispatch,
config,
setItem,
item,
}) => {
const sdk = getSdk(config)
try {
Expand All @@ -92,7 +94,40 @@ export const getAvailability: GetAvailability = async ({
type: 'setAvailability',
payload: { ...delivery, quantity: skuInventory.inventory.quantity },
})
if (setItem) setItem({ [skuCode]: skuInventory })
if (setItem) setItem({ ...item, [skuCode]: skuInventory })
} catch (error) {
console.error('Get SKU availability', error)
}
}

type GetAvailabilityArgs = {
skusIds: string[]
dispatch: Dispatch<AvailabilityAction>
config: CommerceLayerConfig
setItem?: (item: Items) => void
}

export async function getAvailabilityByIds({
skusIds,
config,
setItem,
}: GetAvailabilityArgs) {
const sdk = getSdk(config)
try {
const inventories = await Promise.all(
skusIds.map(async (id) => {
return (await sdk.skus.retrieve(id, {
fields: { skus: ['inventory', 'code'] },
})) as SkuInventory
})
)
const item = {} as Items
inventories.forEach((v) => {
if (v?.code) {
item[v.code] = v
}
})
if (setItem) setItem(item)
} catch (error) {
console.error('Get SKU availability', error)
}
Expand Down
3 changes: 3 additions & 0 deletions src/reducers/SkuReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ type SkuAction = BaseAction<SkuActionType, SkuState>
export type SkuState = Partial<{
skus: Sku[]
loading: boolean
skuCodes: string[]
}>

const actionType: SkuActionType[] = ['getSkus']

export const skuInitialState: SkuState = {
skus: [],
loading: true,
skuCodes: [],
}

type GetSku = {
Expand Down Expand Up @@ -61,6 +63,7 @@ export async function getSku<T extends GetSku>({
payload: {
skus: allSkus,
loading: false,
skuCodes: skus,
},
})
}
Expand Down

0 comments on commit b4ef18e

Please sign in to comment.