How to apply animation to a newly added item to the "beginning" of a virtual list #693
Unanswered
hoffnung8493
asked this question in
Q&A
Replies: 2 comments
-
If you use unique ids for the |
Beta Was this translation helpful? Give feedback.
0 replies
-
I got it working! This animates both adding items and removing items, regardless of where they are in the list. Live Demo: https://stackblitz.com/edit/tanstack-virtual-framer-motion?file=src%2FApp.tsx import * as React from 'react';
import { useWindowVirtualizer } from '@tanstack/react-virtual';
import { motion } from 'framer-motion';
const initialNumbers = Array(10000).fill(null).map(Math.random);
export default function App() {
// The scrollable element for your list
const parentRef = React.useRef<HTMLDivElement>(null);
const [numbers, setNumbers] = React.useState(initialNumbers);
function addNumber() {
setNumbers((numbers) => [Math.random(), ...numbers]);
}
function resetNumbers() {
setNumbers(initialNumbers);
}
function deleteNumber(number: number) {
setNumbers((numbers) => numbers.filter((n) => n !== number));
}
// The virtualizer
const virtualizer = useWindowVirtualizer({
count: numbers.length,
estimateSize: () => 76,
scrollMargin: parentRef.current?.offsetTop,
});
const items = virtualizer.getVirtualItems();
return (
<div style={{ height: '100vh', width: '100vw' }}>
<p>Animate items in and out with TanStack Virtual and Framer Motion</p>
<button onClick={addNumber}>Add a number</button>
<button onClick={resetNumbers}>Reset</button>
<hr />
<div ref={parentRef}>
<div
style={{
height: virtualizer.getTotalSize(),
width: '100%',
position: 'relative',
scrollMargin: parentRef.current?.offsetTop ?? 0,
}}
>
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
// https://tanstack.com/virtual/latest/docs/api/virtualizer#scrollmargin
transform: `translateY(${
(items[0]?.start ?? 0) - virtualizer.options.scrollMargin
}px)`,
}}
>
{items.map((virtualRow) => {
const number = numbers[virtualRow.index];
return (
<div
key={number}
// `data-index` required when using `virtualizer.measureElement`
// https://tanstack.com/virtual/latest/docs/api/virtualizer#measureelement-1
data-index={virtualRow.index}
ref={virtualizer.measureElement}
>
<motion.div
layout="position"
exit={{ scale: 0.75, opacity: 0 }}
style={{ background: 'white', padding: 10 }}
>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
}}
>
<p>{number}</p>
<button onClick={() => deleteNumber(number)}>
Delete
</button>
</div>
</motion.div>
</div>
);
})}
</div>
</div>
</div>
</div>
);
} Note: I'm using |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
I have a list (ex.
[1, 2, 3]
) and this list gets updated at zero index (ex. updated list after a few seconds:[0, 1, 2, 3]
)So this zero would appear at the top of the rendered list. It does work correctly.
Now I want to apply animation to the newly added item, so that its clear to the user that this was newly added. It works if I append new items at the end of the array (updated array: [1,2,3,4]), but it does not work in my case, where I want to append a new item at the very beginning.
Also I realized that the animation would take effect to other items when I scroll away and scroll back due to virtualization. But I only want animation for the new ones, so I have added some basic condition. Based on the condition, only the new item's background is set to red, which is applied properly. But the animation doesnt work for some reason..
Below is the minimum code snippet:
Beta Was this translation helpful? Give feedback.
All reactions