[STR-453] fix: clear stale selectedImageVariationSKU when the selected item changes - #88
[STR-453] fix: clear stale selectedImageVariationSKU when the selected item changes#88iago1501 wants to merge 1 commit into
Conversation
…nges The image variation SKU is only ever set when a colour variation is picked, but nothing invalidated it afterwards. Changing any non-colour specification moved selectedItem to a new SKU while the field kept pointing at the old one, and consumers that give it priority over selectedItem (the product gallery in store-components, and ProductSKUAttributes) kept rendering the previous SKU. Clear it on SET_SELECTED_ITEM, but only when the item genuinely changed and the stored SKU is not the incoming one, so the colour-selection redirect and the provider's re-dispatch on product identity changes both keep working. Co-authored-by: Cursor <[email protected]>
|
Hi! I'm VTEX IO CI/CD Bot and I'll be helping you to publish your app! 🤖 Please select which version do you want to release:
And then you just need to merge your PR when you are ready! There is no need to create a release commit/tag.
|
|
Beep boop 🤖 I noticed you didn't make any changes at the
In order to keep track, I'll create an issue if you decide now is not a good time
|
mendescamara
left a comment
There was a problem hiding this comment.
O diagnóstico e a escolha do reducer como lugar da correção me parecem certos — confirmei que SELECT_IMAGE_VARIATION só é despachado sob isColor (SKUSelector/index.tsx:368-378), que o valor guardado é um itemId (logo a comparação com args.item?.itemId é homogênea) e que ninguém além do provider despacha SET_SELECTED_ITEM.
Tenho uma ressalva, porém, sobre o caso em que o pin realmente tem efeito.
Risco de regressão quando a seleção está incompleta
Quando todas as variações estão selecionadas, selectedItem === selectedImageVariationSKU e o pin é redundante. O pin só muda o que a galeria renderiza quando selectedItem ≠ pin — ou seja, exatamente quando o shopper escolheu uma cor sem ter todas as variações selecionadas. É esse cenário que a mudança pode quebrar:
- URL com
?skuId=35, todas as variações selecionadas. - O shopper desmarca uma variação não-cor (clicar no valor já selecionado →
isRemoving). Não há redirect, a query fica intacta. - O shopper clica numa cor →
SELECT_IMAGE_VARIATION(40)é despachado (SKUSelector/index.tsx:368), masallSelected === false, entãoskuIdToRedirect = nulle rodaredirectToSku(null)→setQuery({ skuId: null })(SKUSelector/index.tsx:267e380-398). skuIdsai da query →useSelectedItemFromIdrefazgetSelectedItem(undefined, items)→ primeiro item disponível (ex.:30), que não é nem o item anterior nem o pin.- No reducer:
itemChanged = trueepointsToAnotherItem = true→ o pin é limpo.
Resultado: o shopper clica numa cor e a galeria volta para as imagens do SKU default. Hoje isso funciona. Os três casos verificados no workspace (pin igual ao item entrante, re-dispatch por identidade de product, item genuinamente diferente) não cobrem esse — ele exige a desmarcação prévia do passo 2.
Sugestão
O sinal que falta ao reducer é se o item veio de uma seleção explícita ou de um fallback. O provider sabe disso:
// ProductContextProvider.tsx:101-104
dispatch({
type: 'SET_SELECTED_ITEM',
args: { item: getSelectedItem(skuId, items), fromQueryString: Boolean(skuId) },
})E no reducer, limpar apenas quando args.fromQueryString !== false (default limpando, para não mudar o comportamento de quem despachar sem o campo).
Isso mantém o bug original corrigido — na troca de Voltagem o redirectToSku('37') coloca skuId=37 na query, então fromQueryString é true — e preserva o pin no caminho de fallback acima.
Vale reproduzir os passos 2-4 no workspace antes de decidir: é o único cenário não coberto, e é onde a feature de fato vive.
Regression sweep on the linked workspaceBecause this changes a reducer that every Before / afterThe scripted flow: pin an image variation on SKU Page load — 14 pagesHome, 2 category pages and 11 PDPs, covering a Every structural metric matched Interaction — 22 swatch clicks across 8 PDPsThe click-by-click trails ( On its own that result proves nothing, and it's worth being explicit about why: through the UI, clicking a colour always redirects to the very SKU being pinned, which is exactly the case the equality guard preserves. That path would never produce a violation, not even against the unfixed code. Sensitivity control — the flow that actually breaksSo I ran the pathological flow (pin a SKU, then change the selection through another route) on 6 products in both environments:
Products: State leakageTwo paths where a context reducer typically leaks were checked on the linked workspace: a category page holding 8 concurrent providers (all pins null), and client-side navigation from a PDP with an active pin out to the category page and into another PDP — the pin did not survive the transition, and the gallery was correct on arrival. About the console noiseThe linked workspace logs more errors than Two products render no price block ( The two images above live on the |


What problem is this solving?
skuSelector.selectedImageVariationSKUis only ever assigned when the shopper picks a colour variation —SKUSelectorguards that dispatch behindisColor(variationName). Nothing ever invalidated it afterwards:SET_SELECTED_ITEMswappedselectedItemand left the field pointing at the previously selected SKU.Two consumers give that field absolute priority over
selectedItem, falling back only when it isnull:vtex.store-components→react/components/ProductImages/Wrapper.js(the PDP gallery)vtex.store-components→react/ProductSKUAttributes.tsxSo once a colour was picked, changing any non-colour specification (Voltage, Size, Model…) moved
selectedItemto the new SKU while the gallery stayed frozen on the images of the old one.The fix clears the field on
SET_SELECTED_ITEM, but only when the item genuinely changed and the stored SKU is not the incoming one. Both guards are load-bearing: the colour selection flow dispatchesSELECT_IMAGE_VARIATIONand only then redirects, landing here with that same SKU, and the provider re-dispatches this action whenever theproductobject identity changes with the item unchanged.Fixes STR-453.
How to test it?
Workspace
On
/classic-shoes/p, click the colour swatch so the image variation gets pinned, then move the selection to a different SKU. Same page and same interaction, before and after this change:selectedItemselectedImageVariationSKU3735(stale)155470,155471— SKU 3537null155474,155475— SKU 37Verified live on the linked workspace that the two guards hold, so the existing colour behaviour is untouched:
productidentity change);react/__tests__/reducer.test.tspins those same branches.yarn testpasses: 2 suites, 11 tests, including the pre-existingProductContextProvidersuite.Describe alternatives you've considered, if any.
Dropping the
isColor()guard instore-components'SKUSelectorso that every variation change dispatchesSELECT_IMAGE_VARIATION. Rejected: it would make the gallery jump to an arbitrary matching SKU while the shopper still has variations unselected, and it leaves the invariant unenforced — any other component that changes the selected SKU would reintroduce the same stale state. Keeping the correction in the reducer holds the guarantee in one place and fixesProductSKUAttributesat the same time.Related to / Depends on
STR-453. No sibling PRs — the fix is contained in this repository, even though the visible symptom is reported against
vtex.store-components.