I am using react-window
FixedSizedList
and react-virtualized-auto-sizer
Autosizer
components to build a list/table UI element that may contain thousands of items that also receives new items via a websocket connection and prepends them to the list. I now have a requirement to animate the entry of new elements in this list.
Here is a codesandbox link with a minimal (and not quite working) example: codesandbox.
Note how the .row
animation is triggered for every child of FixedSizedList
each time the data list receives a new item. Also note how the .row
animation is again triggered for every child of FixedSizedList
when the list is scrolled.
I understand that the reason this is happening is because of how list virtualization works using absolute positioning of the children rows. Every time a new item is inserted into data, or the list is scrolled, react-window
needs to re-compute the style
prop for each row, which recreates every DOM element and hence re-triggers the .row
animation.
I would like to animate only the new .row
DOM elements when they appear.
Things I have tried:
- Add
animation-iteration-count: 1;
to the.row
class. This doesn't work for the same reason mentioned above as every element is re-created on a new item insert. - Animate only the first row (example using red background in the code sandbox). While this "works", it's not quite suitable. In my production site, updates are not guaranteed to come through one at a time - multiple rows might be inserted at the same time. All new rows should be animated when they are added to the DOM. This can be replicated in the code sandbox by inserting two UUID's at once in the hook.
- Not use list virtualization. This of course works fine, but is not suitable. In my production site this list could contain thousands of items.
- Reading this previous question. The previous question is sparse of information, does not have a minimal example, and has no useful answers or comments. Additionally, it is over 5 years old.
How is it possible to achieve the result I'm looking for here?
EDIT:
A further attempt I have tried, extending on 2) above:
- Save a copy of the "old" list of items each render. When an update is received, subtract the length of the old list from the length of the new list (call this number
n
). Animate the topn
items of the new list. This "works", but the production system has some intricacies making this solution insufficient - each list item is dated with an ISO timestamp, and the list is sorted according to timestamp new -> old. Updates received via websocket also have a timestamp, but there is no guarantee the new item will always be newer than the current top of the list - in some cases, new items are inserted into position 2, 3 or further down in the list. In this case, animating the topn
items based on the length change would not be accurate.