question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support passive scroll listeners

See original GitHub issue

Make 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:closed
  • Created 7 years ago
  • Reactions:3
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
bvaughncommented, Sep 28, 2016

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

1reaction
bvaughncommented, Sep 21, 2016

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 and grid-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:

  1. Updated AutoSizer (really the detect-element-resize util) to prevent it from swallowing “scroll” events.
  2. 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 the detect-element-resize script). But the options-support-detection approach is simple enough it doesn’t matter either way.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found