Skip to content

Commit

Permalink
fix(): attempt to eliminate prependItem visual jump
Browse files Browse the repository at this point in the history
Fix #248

Caveat of this approach is that if
the list is scrolled to the bottom, the jump won't work.
  • Loading branch information
petyosi committed Dec 28, 2020
1 parent b28b995 commit 3df9dfc
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 20 deletions.
4 changes: 2 additions & 2 deletions e2e/prepend-items.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ describe('list with prependable items', () => {
document.querySelector('button')!.click()
})

expect(await getScrollTop()).toBe(75)
expect(await getScrollTop()).toBe(110) // 55x2

await page.evaluate(() => {
document.querySelector('button')!.click()
})

expect(await getScrollTop()).toBe(150)
expect(await getScrollTop()).toBe(220)
})
})
34 changes: 19 additions & 15 deletions site/docs/prepend-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,49 @@ sidebar_label: Prepending Items
slug: /prepend-items/
---

Appending items to the list is straightforward - the items at the bottom do not displace the currently rendered ones.
Appending items to the list is straightforward - the items at the bottom do not displace the currently rendered ones.
Prepending items is more complex, because the current items should remain at their location and their indexes should not be offset.

This example shows how to increase the item count and instruct the component that you are prepending items by decreasing the `firstItemIndex` property value when the user scrolls to the top, creating **reverse endless scrolling**.

```jsx live
() => {
const START_INDEX = 10000
const INITIAL_ITEM_COUNT = 200
const INITIAL_ITEM_COUNT = 100

const [firstItemIndex, setFirstItemIndex] = useState(START_INDEX)
const [users, setUsers] = useState(() =>
generateUsers(INITIAL_ITEM_COUNT, START_INDEX)
)
const [users, setUsers] = useState(() => generateUsers(INITIAL_ITEM_COUNT, START_INDEX))

const prependItems = useCallback(() => {
const usersToPrepend = 100
const usersToPrepend = 20
const nextFirstItemIndex = firstItemIndex - usersToPrepend

setFirstItemIndex(() => nextFirstItemIndex)
setUsers(() => [
...generateUsers(usersToPrepend, nextFirstItemIndex),
...users,
])
setTimeout(() => {
setFirstItemIndex(() => nextFirstItemIndex)
setUsers(() => [...generateUsers(usersToPrepend, nextFirstItemIndex), ...users])
}, 500)

return false
}, [firstItemIndex, users, setUsers])

return (
<Virtuoso
components={{
Header: () => <div style={{ textAlign: 'center', padding: '1rem' }}>Loading...</div>,
}}
firstItemIndex={firstItemIndex}
initialTopMostItemIndex={INITIAL_ITEM_COUNT - 1}
data={users}
startReached={prependItems}
itemContent={(index, user) => {
return <div style={{ backgroundColor: user.bgColor, padding: '1rem 0.5rem' }}>
<h4>{user.index}. {user.name}</h4>
<div style={{ marginTop: '1rem' }}>{user.description}</div>
</div>
return (
<div style={{ backgroundColor: user.bgColor, padding: '1rem 0.5rem' }}>
<h4>
{user.index}. {user.name}
</h4>
<div style={{ marginTop: '1rem' }}>{user.description}</div>
</div>
)
}}
/>
)
Expand Down
7 changes: 4 additions & 3 deletions src/upwardScrollFixSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,17 @@ export const upwardScrollFixSystem = u.system(
u.map(unshiftWith => {
const currentTopIndex = u.getValue(listState).items[0].originalIndex!

console.log({ currentTopIndex })
return {
index: currentTopIndex + unshiftWith,
offset: offsetOf(currentTopIndex, u.getValue(sizes)),
}
})
),
({ index, offset }) => {
setTimeout(() => {
const newOffset = offsetOf(index, u.getValue(sizes))
// unshiftWith will alter sizes.
// sizes are statefulStream, that's why we skip the immediate
u.handleNext(u.pipe(sizes, u.skip(1)), sizeValue => {
const newOffset = offsetOf(index, sizeValue)
u.publish(scrollBy, { top: newOffset - offset })
})
}
Expand Down

0 comments on commit 3df9dfc

Please sign in to comment.