Description
I have a potentially long list of items rendered in a react-virtualized VirtualScroll
.
Each item (row) in the list has a fairly large amount of elements, one of which opens a context menu. I'm trying to use react-tether
to render that menu on the HTML body
(so that it's not hidden when the item is at the bottom/top of the scrollable list) and keep the menu 'stuck' to my item while the user scrolls through the list.
My problem is that there is a noticeable lag in updating the position of the tethered menu.
Some of the steps I've taken so far:
VirtualScroll
. The tethered menu was rendered smoothly, no noticeable jank. That's how I concluded that the problem is with react-virtualized
rowRenderer
down to only the menu trigger, as recommended here. shouldComponentUpdate
in the row component. This has improved the perceived performance greatly, reduced the delay greatly but it is still noticeable.Grid.js
and tether.js
.Library Versions:
Working Demo
https://plnkr.co/edit/f7OhCoCXkDsWbyjxhR3f
Screenshot:
FYI that Plnkr was broken. It was including the wrong styles version (8.x instead of 7.x).
After fixing that, the visual "lag" I see is not something I know how to fix with version 7.x. The problem is that the browser manages the scroll in a different thread (so that JS doesn't block it and cause the UI to feel unresponsive). Normally this isn't noticeable because all of the UI is being scrolled together, however in this case- your modal is absolutely positioned, by JS, and so it sometimes lags behind the browser's scroll position.
That being said, upgrading to version 8 gives you an alternative to the portal approach, which does fix the issue, as shown in this updated plunk: https://plnkr.co/edit/NESPMzDz22JjwFVthve4?p=preview
They key is this:
render() {
const { menuOpen } = this.state;
const { index, style } = this.props;
// Make sure open cells are on a higher z-index than others
if (menuOpen) {
style.zIndex = 2;
}
return (
<div
className="row"
style={style}
>
{list[index]}
{/* Render your button OR menu item here */}
</div>
);
}