Support passive scroll listeners
See original GitHub issueMake Grid
use passive scroll listeners (when available) for huge performance improvements.
Reference: https://developers.google.com/web/updates/2016/06/passive-event-listeners
Since React does not support passive event listeners (yet: https://github.com/facebook/react/issues/6436), we have first to test for browser support using the following module (coded in es7 + flowtype):
/* ListenerOptions.js
* @flow
*/
let passive: boolean = false;
const testOptions = {
get passive() {
passive = true;
},
};
try {
// $FlowIssue: addEventListener type hint does not support options yet
document.addEventListener('test', null, testOptions);
} catch (e) {
// ignore
}
export default {
hasPassive: passive,
};
export function addPassiveEvent(element: HTMLElement, eventName: string, handler: EventHandler) {
const options = passive ? { passive: true } : false;
// $FlowIssue: addEventListener type hint does not support options yet
element.addEventListener(eventName, handler, options);
}
Then instead of attaching using react’s onScroll
component prop, get the elements ref and add the event handler directly (or using the helper function in ListernerOptions
).
/* @flow */
import React from 'react';
import { addPassiveEvent } from './ListenerOptions';
export default class PassiveScroller extends React.Component {
onScrollerRef = (scrollerElement:HTMLElement) => {
if (!scrollerElement) {
if (this.scrollerElement) {
// Prevent memory leaks
this.scrollerElement.removeEventListener('scroll', this.onScroll);
}
this.scrollerElement = null;
return;
}
this.scrollerElement = scrollerElement;
addPassiveEvent(scrollerElement, 'scroll', this.onScroll);
};
onScroll:EventHandler = (event) => {
// Normal scroll handler
};
scrollerElement: ?HTMLElement = null;
render() {
return (
<div
ref={this.onScrollerRef}
>
{this.props.children}
</div>
);
}
}
I can submit the PR if there are no objections.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:3
- Comments:8 (7 by maintainers)
Top Results From Across the Web
Use passive listeners to improve scrolling performance
Learn how to improve your page's scrolling responsiveness by avoiding passive event listeners.
Read more >Passive event listeners | Can I use... Support tables for ...
Primarily intended to be used with touch events and wheel events. Since they cannot prevent scrolls, passive event listeners allow the browser to...
Read more >javascript - What are passive event listeners?
Passive event listeners are an emerging web standard, new feature shipped in Chrome 51 that provide a major potential boost to scroll performance....
Read more >Use passive listeners to improve scrolling performance
Adding a passive: true flag to the event listener tells the browser to allow page scrolling immediately, rather than wait for the script...
Read more >Passive Event Listeners: Solution to ''Does not use ...
What are passive event listeners and how to use them to improve your website's scrolling performance? Let's see how to fix the audit!...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
By the way, I pushed my work-in-progress branch if you have any interest in checking it out: https://github.com/bvaughn/react-virtualized/tree/passive-scrolling
It has very minimal changes: https://github.com/bvaughn/react-virtualized/compare/passive-scrolling?expand=1
Okay. I’ve got a branch locally where I’ve experimented with this a bit. Surprisingly, I don’t see any improvements for my test harnesses (eg
table.html
andgrid-test.html
) using the Chrome Timeline view.It’s gotten late. I’ll continue exploring this. Feel free to jump in and experiment with me if you’d like!
I’ve pushed a branch,avoid-unnecessary-reflows
, where I made 2 changes:UpdatedAutoSizer
(really thedetect-element-resize
util) to prevent it from swallowing “scroll” events.Try to cut down on unnecessary reflows while scrolling.If you decide to jump in and help- consider starting from that branch. (Totally your call.)Edit: The above changes have been merged to
master
and released as 8.0.6 FYI.Your above options-support detection code looks fine. There’s also the
event-listener-with-options
module, based on the WICG polyfill which might be a good option in terms of keeping react-virtualized as simple as possible (eg I hate the fact that I had to bundle thedetect-element-resize
script). But the options-support-detection approach is simple enough it doesn’t matter either way.