Skip to content

Commit

Permalink
fix(masonry-wall): prevent item duplication due to race condition
Browse files Browse the repository at this point in the history
Closes #326
  • Loading branch information
DerYeger committed Aug 30, 2024
1 parent 6b3f5e1 commit ac9b404
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/great-zoos-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@yeger/vue-masonry-wall-core': patch
---

prevent item duplication due to race condition
18 changes: 13 additions & 5 deletions packages/vue-masonry-wall-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,18 @@ export function useMasonryWall<T>({
columns.value = newColumns
}

async function fillColumns(itemIndex: number) {
let currentRedrawId = 0

async function fillColumns(itemIndex: number, assignedRedrawId: number) {
if (itemIndex >= items.value.length) {
return
}
await nextTick()
if (currentRedrawId !== assignedRedrawId) {
// Skip if a new redraw has been requested in parallel,
// e.g., in an onMounted hook during initial render
return
}
const columnDivs = [...wall.value.children] as HTMLDivElement[]
if (rtl.value) {
columnDivs.reverse()
Expand All @@ -137,22 +144,23 @@ export function useMasonryWall<T>({
: prev,
)
columns.value[+target.dataset.index!]!.push(itemIndex)
await fillColumns(itemIndex + 1)
await fillColumns(itemIndex + 1, assignedRedrawId)
}

async function redraw(force = false) {
if (columns.value.length === columnCount() && !force) {
const newColumnCount = columnCount()
if (columns.value.length === newColumnCount && !force) {
if (vue === 2) {
;(emit as Vue2ComponentEmits)('redraw-skip')
} else {
;(emit as Vue3ComponentEmits)('redrawSkip')
}
return
}
columns.value = createColumns(columnCount())
columns.value = createColumns(newColumnCount)
const scrollTarget = scrollContainer?.value
const scrollY = scrollTarget ? scrollTarget.scrollTop : window.scrollY
await fillColumns(0)
await fillColumns(0, ++currentRedrawId)
if (scrollTarget) {
scrollTarget.scrollBy({ top: scrollY - scrollTarget.scrollTop })
} else {
Expand Down

0 comments on commit ac9b404

Please sign in to comment.