Comments (7)
@kiejo , good suggestion (thought about it, but not tried)
Also different threshold of intersection can be used with really small steps - like [0.001, 0.002..., 1] to catch shifts/changes in intersection - but intersection handler can evaluate frequently and not cover cases where 0.001 is hundreds of pixels.
from react-viewport-list.
Hi, @kiejo
Most other virtualization libs use simple onscroll event. I tried some approaches with onscroll/intersection observer/non endless animation frame but unsuccessfully.
I think intersection observer for spacers (a div which fills virtualized space) can be used and I made some drafts with it a time ago. Mostly it works fine. I want to move to this solution in future if I'll make it good in all cases.
I need a way to know when elements changed their positions near viewport - it can be scroll, parent resize, shifts by elements added on top/bottom, window resize, item height change... Endless request animation frame handle all of these "events".
from react-viewport-list.
Thanks for the quick answer and explanation! Using an intersection observer that spans the list's viewport sounds like a good potential approach to detect when elements move out of or into the viewport. I will have to look at the current implementation in more detail to better understand how everything works at the moment.
It's great to hear that it's a topic that is already on your radar and that might get addressed in the future. Thanks for the great library!
from react-viewport-list.
@kiejo I can explain current logic deeply.
Every frame I compute rects of spacers, first/last rendered list items and viewport bounds. Then I check is everything shown inside viewport without free spaces. If I need to render more items, I change "indexes to render", but it's some kind of estimation - at next frame indexes may be corrected.
Logic now: render some items -> check that all items fill viewport -> correct indexes to fill viewport.
When you scroll last item can be fully intersect the viewport - this is the moment I change indexes for example.
from react-viewport-list.
That's an interesting approach. It sounds like an IntersectionObserver
with the list container as its root
could be used to detect whenever a spacer element intersects (or stops intersecting) with the list rect. Whenever the spacer intersects, more items would need to be rendered until the observer fires again indicating that the spacer does not intersect anymore and got pushed out of the list rect. The rootMargin
of the observer could be used to handle an overscan so that new items are rendered sooner.
A similar mechanism could be used to detect when items need to be removed. A second observer with a wider rootMargin
could be used to check when a spacer element gets pushed too far out of the list rect. That would indicate that items can be removed from the DOM.
I haven't tried any of this, but in theory I think this could potentially handle cases like scrolling, parent/window resize, new elements being added within the rendered range, and height changes of rendered items.
I'm sure there are many more cases to handle and and an approach like this would need more exploration and prototyping to verify if it's actually viable. I also don't know what the overall performance would then look like, but the idle CPU usage should definitely be lower if this approach works.
It sounds like you may have already thought about something like this as you mentioned you already made some drafts using IntersectionObserver
. Just thought I'd share some ideas in case you haven't thought about some of these yet.
from react-viewport-list.
@kiejo Yes, I made exactly you described with IntersectionObserver
. The problem with observer is it fired only once - when "intersection" changed. So bad case is when spacer intersect viewport, we render new items, but new rendered items not fill the free spaces and spacer still intersect viewport - at this case virtualization will be broken. I fix it by reobserve anytime on indexes change (this is a part where rAF is more performant) - but this sulution has some pitfalls too. Also I tried to use "check" on layout effect instead of reobserve on index change and catch max state update error in react sometimes 😅
Anyway I think intersection observer is a good way to "make it right" without hacky rAF.
from react-viewport-list.
Good to hear that you already tried this approach :)
The problem with observer is it fired only once - when "intersection" changed. So bad case is when spacer intersect viewport, we render new items, but new rendered items not fill the free spaces and spacer still intersect viewport - at this case virtualization will be broken.
Maybe something like this could help with this case:
Whenever the observer gets notified about the spacer intersecting, start an update loop that keeps adding more items until the observer gets notified that the spacer does not intersect anymore.
function update() {
// Needs to stop the update loop when the start/end of the items array is reached and the
// items do not take enough space to push the spacer element out of the list rect (prevent
// endless update loop).
}
let frameId = null
function updateLoop() {
frameId = requestAnimationFrame(updateLoop)
update()
}
function startUpdateLoop() {
if (!frameId)
updateLoop()
}
function stopUpdateLoop() {
if (frameId) {
cancelAnimationFrame(frameId)
frameId = null
}
}
const observer = new IntersectionObserver(entries => {
if (entries[0].isIntersecting)
startUpdateLoop()
else
stopUpdateLoop()
}, {
root: listElement,
threshold: 0,
})
observer.observe(spacerElement)
This is just some ideation on how this could potentially work and I'm sure the logic would need to handle more cases.
from react-viewport-list.
Related Issues (20)
- Thank you HOT 3
- New items added to bottom of list. After refresh, appeared first. HOT 6
- Incorrect page scrolling behavior when `initialIndex` or `scrollToIndex` is used HOT 4
- Why does it work when height varies? HOT 2
- List items rendered with undefined HOT 2
- Endless Scrolling Loop HOT 28
- scroll to bottom while having async rendering items HOT 2
- Scroll to bottom on initial render HOT 2
- flew wrap not work HOT 1
- Is infinite scroll pagination supported? HOT 1
- Scroll to position HOT 3
- remove spacer in list HOT 3
- Scroll X and Scroll Y and sticky rows and columns HOT 3
- Is SSR supported? HOT 8
- Any way to show a dynamic number of columns? HOT 2
- Unexpected scroll jump with initialIndex set to last item HOT 8
- Having trouble getting axis="x" to work HOT 3
- justify-content: flex-end; hides the scroll bar. HOT 2
- Styling is breaking if used in material ui table HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-viewport-list.