Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] Disable / control unmounting of already mounted rows #234

Closed
olee opened this issue May 5, 2019 · 14 comments
Closed

[Feature request] Disable / control unmounting of already mounted rows #234

olee opened this issue May 5, 2019 · 14 comments
Labels

Comments

@olee
Copy link

olee commented May 5, 2019

I would like to suggest an option to control the unmounting of already mounted rows.
This could give a performance boost to lists with a moderate amount of large rows but which are very expensive to render.
If properly handled (rows should use memo of course) it would only render rows the first time they are visible and then keep them mounted to be able to scroll back to them again without needing to render them again.

What do you think of this suggestion?
Might there be a way to do this with current react-window (or maybe react-virtualized?) right now?

@bvaughn
Copy link
Owner

bvaughn commented May 5, 2019

I don't think that sounds like something I want to support directly. It sounds like a reasonable use case, I just don't think I want to take on the extra complexity.

You could perhaps implement this behavior by supplying your own innerElementType that's stateful and maintains a list of rows it's created by inspecting its props:

createElement(innerElementType || innerTagName || 'div', {
children: items,
ref: innerRef,
style: {
height: isHorizontal ? '100%' : estimatedTotalSize,
pointerEvents: isScrolling ? 'none' : undefined,
width: isHorizontal ? estimatedTotalSize : '100%',
},

But this would require some hacky duplication of this code:

const items = [];
if (itemCount > 0) {
for (let index = startIndex; index <= stopIndex; index++) {
items.push(
createElement(children, {
data: itemData,
key: itemKey(index, itemData),
index,
isScrolling: useIsScrolling ? isScrolling : undefined,
style: this._getItemStyle(index),
})
);
}
}

@Bnaya
Copy link

Bnaya commented Jun 2, 2019

Out of curiosity:
What's the painful part in your use-case? the DOM creation or react rendering?
I think another approach is implementing DOM reuse, but it will require adding intermediate level of virtual keys.

@olee
Copy link
Author

olee commented Jun 4, 2019

Keeping react components mounted is pretty much the same as DOM reuse.
The initial rendering of new react nodes (ie. nodes that were added or have a new key) is the most expensive part of react rendering - subsequent updates are way faster.
This is why I would love to see a library supporting virtual scrolling, but at the same time keeping already rendered components mounted (because as long as they don't exceed a quite large amount, this should be faster).

PS: Oh yeah another option for "DOM reuse" might be a way to make the virtual scrolling reuse the item keys.
This should result in just their content being updated without making react disposing the old DOM elements and creating new ones.
However for this to work the items would have to be implemented in a way that ensures they do not totally rely on componentDidMount for some rendering logic.

PPS: Actually I think this idea might be worth a try to see what performance benefits can me achieved with such a solution - I guess it could be tried out by adding a third parameter containing this kinda "window-static-key" here: https://github.com/bvaughn/react-window/blob/master/src/createListComponent.js#L305
So react-window would have to create a list of keys and once an item is rendered it get's assigned a key and will keep it, until it leaves the rendered range.
Then the newly visible items would get that key assigned.

@Bnaya
Copy link

Bnaya commented Jun 6, 2019

@olee
I'm exploring possibilities when exposing the up-to-date overscan information to the keyProvider and cell components (its a patch on react-window),
https://codesandbox.io/s/github/Bnaya/sticky-eurovision/tree/iteration
Take a look at src/implementations/WithReactWindowDOMReuse/WithReactWindowDOMReuse.tsx

Using custom keyProvider and modulo i'm able to (almost) keep using same keys, and rotating them.

I think the idea behind it works,
but right now react-window changing the overscan values in an unexpected way (for me) after the scroll ends. (losing one row and gaining it again right before next scroll)
I will keep exploring that direction

@Bnaya
Copy link

Bnaya commented Jun 6, 2019

I've made another iteration, when i'm using component state to track recycling, looks very promising
In the picture we can see row 17 takes the components instances of row 2
Screen Shot 2019-06-06 at 17 13 02

There is still an issue when you scroll up to the ends and the rendered rows number is changing.

@ghost
Copy link

ghost commented Jun 15, 2021

I have the same problem here...
It would be great if there was a way which already-rendered items that fall out of the view, still be there and not unmount.

@bvaughn
Copy link
Owner

bvaughn commented Jun 15, 2021

It would be great if there was a way which already-rendered items that fall out of the view, still be there and not unmount.

Since this is something React intends to provide support for natively with a future Offscreen API, I don't think a library like react-window should try to implement this itself.

@codeaid
Copy link

codeaid commented Oct 25, 2021

This is actually something that is causing some pain in the project I'm working on. I have a table where you can select and deselect rows and obviously they change background color. For a long time I couldn't understand why none of my CSS transitions were working until I realised that react-window is completely unmounting all my rows even though the only thing that changes is only the selected property on one of them.

Is there any reason why everything has to be destroyed when things that are not even relevant to virtualization change?

@joseteIIo
Copy link

Agree with @codeaid . It's also a big pain point for a project I am a part of.

@erikiva
Copy link

erikiva commented Sep 1, 2022

Having the exact same problem as @codeaid with a List, is there any way around this?

@CarlosVergikosk
Copy link

CarlosVergikosk commented Apr 20, 2023

Same here, big pain. @codeaid

@JustynaKK
Copy link

hi, did anybody found nice workaround? I have very expensive initial rendering and I am looking for the way to avoid unmounting

@CarlosVergikosk
Copy link

hi, did anybody found nice workaround? I have very expensive initial rendering and I am looking for the way to avoid unmounting
@JustynaKK use virtuoso.

@JustynaKK
Copy link

@CarlosVergikosk hi, I was checking virtuoso, but there is the same thing, everythig is unmounted on scroll

@bvaughn bvaughn closed this as completed Aug 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants