You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

react-smart-scroll

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-smart-scroll - npm Package Compare versions

Comparing version

to
1.0.5

8

es/ReactSmartScroll/index.js

@@ -0,1 +1,3 @@

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }

@@ -14,6 +16,7 @@

data = props.data,
overflow = props.overflow,
row = props.row,
rowHeight = props.rowHeight,
style = props.style,
rowProps = _objectWithoutProperties(props, ['className', 'data', 'row', 'rowHeight', 'style']);
rowProps = _objectWithoutProperties(props, ['className', 'data', 'overflow', 'row', 'rowHeight', 'style']);

@@ -81,3 +84,3 @@ var _useReducer = useReducer(function (state, action) {

'div',
{ ref: scrollRef, className: className || '', style: style },
{ ref: scrollRef, className: className || '', style: _extends({ overflow: overflow }, style) },
React.createElement(

@@ -104,2 +107,3 @@ 'div',

data: [],
overflow: 'auto',
row: function row() {

@@ -106,0 +110,0 @@ return null;

@@ -5,2 +5,4 @@ 'use strict';

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _utils = require('./utils');

@@ -35,6 +37,7 @@

data = props.data,
overflow = props.overflow,
row = props.row,
rowHeight = props.rowHeight,
style = props.style,
rowProps = _objectWithoutProperties(props, ['className', 'data', 'row', 'rowHeight', 'style']);
rowProps = _objectWithoutProperties(props, ['className', 'data', 'overflow', 'row', 'rowHeight', 'style']);

@@ -102,3 +105,3 @@ var _useReducer = (0, _react.useReducer)(function (state, action) {

'div',
{ ref: scrollRef, className: className || '', style: style },
{ ref: scrollRef, className: className || '', style: _extends({ overflow: overflow }, style) },
_react2.default.createElement(

@@ -125,2 +128,3 @@ 'div',

data: [],
overflow: 'auto',
row: function row() {

@@ -127,0 +131,0 @@ return null;

{
"name": "react-smart-scroll",
"version": "1.0.4",
"version": "1.0.5",
"description": "Smart Scroll React Component for long lists",

@@ -17,2 +17,3 @@ "author": "Steven Sacks",

"main": "lib/index.js",
"module": "es/index.js",
"files": [

@@ -19,0 +20,0 @@ "es",

@@ -5,23 +5,28 @@ # react-smart-scroll

If you're looking for a lightweight, high-performance, easy-to-use way to render long lists efficiently in React, you found it.
ReactSmartScroll is a lightweight, high-performance, easy-to-use way to render long lists efficiently in React. It only renders the visible rows, with a few buffer rows above and below.
"Smart Scrolling" only renders the visible rows, with some buffer rows above and below. It supports dynamic height rows.
ReactSmartScroll is un-opinionated, with minimum configuration. It has automatic support for variable height rows, even if they change height at runtime due to resizing, expanding, etc.
react-smart-scroll is way more efficient and way easier to use than react-window or react-virtualized.
**This component uses React Hooks, so it requires React 16.8.x or above.**
It is un-opinionated, and gives exactly you what you need with minimum configuration. Namely, fast rendering of long lists, and automatic support for variable height rows, even if they change height at runtime due to resizing, etc.
## How To Use
ReactSmartScroll is designed to be simple to use. You can check the `demo` folder for an example, as well.
**This component uses React Hooks, so you'll need to be running React 16.8.x or above.**
At its most basic, you pass an array of data and a row component to render the items in the array.
## How To Use
You can check the `demo` folder for some example code, but here's how it works.
All of the props are optional. If you don't provide any data or a row component, it won't render anything, but it won't cause any errors, either.
You need to apply `height`, either in the css class or the style object. You can use a specific height, or `calc()`.
Due to a CSS limitation with how overflow works with padding, `height: 100%` does not work.
The `overflow` default value of `auto` is applied via `style`. So, if you want to use a css class to control it, you need to pass `null`, `undefined`, or an empty string to `overflow`. If you use a style object, you can set it there, since the default `auto` is applied before your style object and thus can be overwritten that way.
#### Props
There are no required props. If you pass nothing, you'll get nothing.
- `className` - A css className that will be applied to the component.
- `data` - An array of items - each item will be passed to your row component. See below.
- `row` - Your row component function/class.
- `rowHeight` - Starting row height (100 by default) - it starts with this as an estimate and adjusts to what the real height of each row is as you scroll.
- `style` - A style object applied to the component if you prefer this to a className.
- `data` - An array of items to be passed to your row component.
- `overflow` - You can set this to `auto` or `scroll` ("auto" is the default).
- `row` - Your row component.
- `rowHeight` - Starting row height (100 by default) - it starts with this as an estimate for all rows, and then measures and caches the actual height of each row is as you scroll.
- `style` - A style object applied to the component if you prefer using inline styling instead of css.
- `...rowProps` - Any additional props you pass will be applied to your row components, for example `onClick`.

@@ -35,2 +40,3 @@

data={data}
overflow="scroll"
row={TestRow}

@@ -49,48 +55,22 @@ onClick={() => console.log('Hello!')} // passed to row components

The `data` array can be made up of whatever you want. ReactSmartScroll does not care. It simply passes the data directly to your row component as-is.
The `data` array can be made up of objects or strings. ReactSmartScroll passes the items in the array directly to your row component so you have complete freedom in how the rows render. If you pass an object with an `id` property, it will use the `id` as the key for each row, which can be more efficient than using the row index.
If you pass an object with an `id` property, it will use the id as the key for each row, which can be more efficient than using the row index. But you don't have to.
Your row component receives the following props:
- `data` - The item in the data array that corresponds to this row.
- `height` - The current measured height of this row. It's provided mainly for debugging, but if you have a use for it, go for it.
- `rowIndex` - The index of the item in the data array. Same as height - provided for debugging, use if you like.
- `rowRef` - NECESSARY! You need to include `ref={rowRef}` prop on your row component's container element, whatever that is. This is how it computes the height of each row. Even if your rows are all the same height, you need to include this in your row component. It makes the rendering more efficient.
- `...rowProps` - Any additional props you passed to the ReactSmartScroll component will be available on every row by the same name. Just don't overwrite the 4 passed props. Or do and watch things break. Or not. I haven't tried it myself.
- `height` - The current measured height of the row. It's provided for debugging or if you have a use for it.
- `rowIndex` - The index of the item in the data array. Also provided for debugging, use if you like.
- `rowRef` - *required* You need to include `ref={rowRef}` prop on your row component's container element.
- `...rowProps` - Any additional props you passed to the ReactSmartScroll component will be available on every row.
## Important!
This component does not have any default styling. You need to provide at least two properties in the css class or the style object. I didn't want to assume anything and wanted to give complete flexibility in how to implement it.
1. `height` - You need to provide a height or it won't work. `height: 100%` may not be predictable. Favor `calc()`.
2. `overflow-y` You must include `auto` or `scroll`.
I recommend rendering your list and figuring out what the average row height will be and setting rowHeight to that.
## How It Works
It's simple, really. And that's why it's so fast. And it's why I think other solutions are way over-engineered... but I digress.
ReactSmartscroll renders enough rows to fill the visible space of the scroll area, plus an extra one above and below. It measures the height of each of the visible row and caches that height as you scroll (or resize) so that the next render of the same row is more efficient. It simulates the total height of all the items by adjusting the padding top and bottom of the div that contains the rows as you scroll.
It renders enough rows to fill the visible space of the scroll area. It measures the height of each of the visible row and caches it as you scroll (or resize) so that the next render of the same row is more efficient.
It always makes sure to include enough buffer above and below to never have an empty space while you scroll up and down.
It accomplishes simulating the total height of all the items by padding the top and bottom of the div that contains the rows. That's it! I told you it was simple. This is also why you have to set the height to a specific value and not a percentage. Percentage heights don't get along with css padding. It's not a bug, it's a feature.
There's no wrapper divs for your rows, absolute positioning, or polyfills for element observables. It's literally just two divs wrapped around your row components. I just did the hard part of figuring out the math for calculating the height.
And yes, if you look at the source, you'll see I'm using for loops for the top and bottom padding calculations. That's because they're an order of magnitude faster than map/reduce and since they're being called every time you scroll or resize, they needed to be high performance, especially if you have a really long list.
If you know how to speed up the calculations and make them faster way, please let me know.
Finally, if you're wondering why I have to add 17 pixels to the bottom padding, you're not alone. I have no idea why that's required for the calculations to be correct, but it is. The mysteries of CSS never end. If you know the answer, tweet it at me.
Unlike other virtual scrolling components/libraries out there, there are no unnecessary wrapper divs for your rows, it doesn't use absolute positioning, and doesn't require any polyfills.
#### Disclaimer
The latest version of Firefox doesn't seem to honor React's rendering speed with `useLayoutEffect()` or `useEffect()`, so if you grab the scrollbar and scroll up and down really fast, you'll see blank space momentarily. Not sure why Firefox hates React, but it's not my bug. Chrome doesn't have this problem.
#### Firefox Note
The latest version of Firefox doesn't seem to keep up with React's rendering speed with `useLayoutEffect()` or `useEffect()`, so if you grab the scrollbar and scroll up and down really fast, you'll see blank space momentarily. Other browsers don't appear to have this problem. Using the mouse wheel to scroll looks good in all browsers.
The good news is that using the mouse wheel to scroll looks good in all browsers.
## Future Stuff
I'm working on the ability to jump to a specific row in the list. This isn't as easy as you might think. It will probably be a prop called `startIndex` or something. I haven't decided that, yet.
I'm working on the ability to scroll to a specific row in the list programmatically.
If you have any feature ideas, be sure to let me know in the github issues. As long as it doesn't bloat the code, I'll consider it.
I hope you enjoy using this component as much as I enjoyed making it!

@@ -104,10 +84,3 @@

[build-badge]: https://img.shields.io/travis/user/repo/master.png?style=flat-square
[build]: https://travis-ci.org/user/repo
[npm-badge]: https://img.shields.io/npm/v/npm-package.png?style=flat-square
[npm]: https://www.npmjs.org/package/npm-package
[coveralls-badge]: https://img.shields.io/coveralls/user/repo/master.png?style=flat-square
[coveralls]: https://coveralls.io/github/user/repo