npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-performant-scrollable-list

v1.0.5

Published

react-performant-scrollable-list

Readme

react-performant-scrollable-list

This plugin is implementing a "windowing" technique on list items (rows) based on very thin layer that can be added easily to any project.

Story

In the past 2 years I worked a lot with infinite-scroll lists, some of them rendered as <li> tags below <ul>, and the others were rendered as table with <tr>s and <td>s.

I was mostly dealing with the rendered tables. Those tables were having something in common, they were fetching the data in 5-10 seconds, they have some special styles or classNames, in addition they've IDs for each Cell <td> with row index for the automation team to have access and interact with the elements using Selenium. All these requirements for every Table Cell in the system forced me to think about a way of implementing some abstract React Component that force me and the future newcomers to implement the must-have things, such as: IDs and other data associated with the rendered DOM element, without forgetting this again and again.

So I implemented each Table Cell as a React Component (with abstract class! - Functional Programmers, please don't start ;)).. After a while I felt that the scroller is heavier and the page lag too much, so I inspected the Performance using Chrome Devtools and saw many shouldComponentUpdate executions! [I was strict to implement it for each Table Cell].

Seems like having that much of components into the React reconciliation is making the process slow. So instead of running ShouldComponentUpdate 7 times for 7 Table Cells per row (some table may reach more than 400 row), I thought of wrapping the whole row with one ShouldComponentUpdate that will return true or false based on row visibility which already known as "Windowing". There's so many popular libraries but I thought of simplicity by implementing this with just two components using Render Props.

  • That gave me to throw all the special implementation of ShouldComponentUpdate per table cell and to save the time of ammending the functions when adding more props to a specific Cell!

  • Reduced the processing time fair enough and raised the performance

Install

npm i -S react-performant-scrollable-list 

Usage

// You can use default import, I prefered the named one
import { PerformantScrollableList } from "react-performant-scrollable-list";

....

  public render() {
    return (
      (
        <div
          id="scrollable-area"
          ref={node => this.scrollableArea = node}
          style={{
            overflowY: "scroll",
            height: "50%",
          }}
        >
          <h1 style={{ marginTop: "120px"}}>Test</h1>
          <PerformantScrollableList.Provider
            wrappedSelectorId="myTable"
            itemSelector="tr"
            render={({isVisibleRow}) => (
              <table
                id="myTable"
                style={{
                  width: "100%",
                }}
              >
                <tbody>
                  {
                    this.state.tableList.map((x, index) => (
                      <PerformantScrollableList.Consumer
                        key={x.id}
                        isVisible={isVisibleRow(index)}
                      >
                      <tr className={`tr_${index}`}>
                        <TableCell value={x.column1} />
                        <TableCell value={x.column2} />
                        <TableCell value={x.column3} />
                        <TableCell value={x.column4} />
                        <TableCell value={x.column5} />
                        <TableCell value={x.column6} />
                        <TableCell value={x.column7} />
                        <TableCell value={x.column8} />
                        <TableCell value={x.column9} />
                        <TableCell value={x.column10} />
                      </tr>
                      </PerformantScrollableList.Consumer>
                    ))
                  }
                </tbody>
              </table>
            )}
          />
        </div>
      )
    );
  }
  

See Examples folder.

API Interfaces

interface IPerformantScrollableListConsumerProps {
  // This prop is passed to each Table Cell based on Provider.isVisibleRow render-prop output
  isVisible: boolean;
}

interface IPerformantScrollableListProviderProps {
  // The wrapped selector ID below the Provider
  wrappedSelectorId: string;
  // The item row selector (e.g. tr, li, .my-row-class, etc.)
  itemSelector: string;
  // Rebase on scroll row counts - When freezing the values user may watch older values that not make since (e.g. sorting)
  // while scrolling up for the already rendered values, so once he pass a speicfic count of rows the Proiver will
  // forceUpdate the values to fetch the last correct value kept in the inner state
  rebaseOnScrollRowCounts?: number;
  // a render-prop to inject the Consumers below that provider, which isVisibleRow(index) will be given to 
  // each consumer to decide whether it's visible or not in the scrollable area
  render(object: {isVisibleRow(index: number): boolean}): JSX.Element;
  // getScrollableParent is implemented by default, but for those who is using some special scroller they may have
  // some issue depending on the built-in implementation. e.g. I use slim-scroll in various projects and it's 
  // scrollable area is not overflowed as "scroll"! but it's implemented in another way that the scrollable area
  // will be overflowed as "hidden", so this prop can give the user to implement that in some cases where needed
  getScrollableParent?(wrappedSelectorId: string): HTMLElement;
}

Limitations

Only works on rows with the same height (static not dynamic) so if your rows height is not equal consider using another "windowing" library.