Closed rossknudsen closed 5 years ago
There's no way to scroll past an offset of 0, unfortunately. So the only way you could implement something like that would be to use a hack similar to what you describe.
Bidirectional infinite scrolling doesn't sound like a common enough use case (in my opinion) to be something I'd want to invest a ton of effort into to be honest.
No worries, just thought I'd post in case there was some value in it. Will close.
Maybe a newsfeed that loads new stories at the top would be another example?
Hi @bvaughn So there isn't any solution for bidirectional infinite scrolling with virtualized lists? or any trick you suggest?
@AliNazariii +1
@bvaughn This feature would be very helpful and great extension for this awesome library (which solving big pain already).
For example "vertical chat messages list" - Initially It should be rendered with scrolled to the latest item, and user should scroll backwards through the chat history.
I'm currently trying to find some hack for backwards vertical scrolling for exact case in my app.
Hi @osadchiynikita, Please inform me if you found a solution to use the virtualized list in a messaging app.
@AliNazariii
I’m trying to do POC now using another lib - https://virtuoso.dev/
@osadchiynikita yeah, I tried it, too. But it had some problems in a bidirectional scroll. On backward vertical scrolling, it goes up and then it comes where I was before the scroll. But tell me your result after your trying.
@AliNazariii Yes, I also have issue with scrollbar position after load more 😕
I had the same issue with Virtuoso because it seems to need to update two props to scroll when using backwards vertical scrolling. What did you guys end up using for virtual scroll??
@osadchiynikita @AliNazariii I'm in need of bi-directional infinite scroll component as well. Did either of y'all land on a solution or able to hack together something with an existing library?
@osadchiynikita @AliNazariii @birdwell @rossknudsen
I have something similar implemented, only I use it on the horizontal axis. Here's the excerpt that handles this. I also don't just add new items, but take items from one end add more on the other side.
I'll be happy to answer any questions and also would love to hear any ideas for optimizing this mess.
One more thing, this is just the excerpt that handles the removing/adding items and repositioning the scroll, some variables might be hanging or missing.
// this would most likely be better with onLayoutEffect, to prevent unnecessary paints.
useEffect(() => {
if (!refPrefScroll.current) return;
// diffPeriodo - Math.abs(internalPeriodo[1].diff(internalPeriodo[0], 'days')) + 1, basically it's the number of total items rendered by the list
// widthDia - item width.
// zoom - number of items being shown on the screen (container.clientWidth / widthDia) +-.
// left, new scrool left that should keep the previous day visible
let left = (diffPeriodo / 2) * widthDia - widthDia / 2;
if (refPrefScroll.current.dir === 'left' && zoom > 1)
left -= (zoom - 1) * widthDia;
refPrefScroll.current = undefined;
document.getElementById(areasProp[0].key + ':trilho')?.scrollTo({
left,
});
}, [refPrefScroll.current]);
const handleScroll = React.useCallback(
(event, areaKey) => {
// header - the outside element of the grid, the container of all items
const header = document.getElementById(ID_CABECALHO);
if (!header) return;
// periodoHandling is just a control prop, it determines if the periodo should be changed, allowPeriodoChange is just a lock for another part of the system that needs to prevent the change for the next render.
if (periodoHandling === 'dynamic' && refControleScrollZoom.current.allowPeriodoChange) {
if (event.scrollLeft + header.offsetWidth >= header.scrollWidth) {
setInternalPeriodo((cur) => {
const newP = cur.slice() as [moment.Moment, moment.Moment];
newP[0] = moment(newP[0]).add(15, 'day');
newP[1] = moment(newP[1]).add(15, 'day');
load(false, newP); // this just loads new items. false make it not force the new download if not necessary, newP is an override for the time frame, you can consider newP the new page.
return newP;
});
// here i can use ref since the only update that matters on this happens at the same time a setState is called
refPrefScroll.current = { dir: 'left' };
} else if (event.scrollLeft === 0) {
setInternalPeriodo((cur) => {
const newP = cur.slice() as [moment.Moment, moment.Moment];
newP[0] = moment(newP[0]).subtract(15, 'day');
newP[1] = moment(newP[1]).subtract(15, 'day');
load(false, newP);
return newP;
});
refPrefScroll.current = { dir: 'right' };
}
}
},
[],
);
Hey all,
I had to implement a time picker for work that was modeled off of an existing UWP/WPF component. The picker could scroll infinitely (or at least appeared to) in either direction, allowing the user to scroll to find the time they wanted in either direction.
I forked an existing codesandbox example to prove that react-window could do the job - which it did. But one thing I couldn't achieve was the ability to scroll infinitely in the upward direction. I'm guessing that the list index is bounded to zero and cannot be negative, so I worked around it by setting the starting point far into the "future" thereby setting the index to a high number. See the line:
const numberOfDaysToScrollTo = 1000;
Just wondering if there is another way to solve this, or whether its a feature that you'd consider adding - it may have been proposed before.
But anyway, thanks for the awesome library.