Skip to content

Commit 9e4a3f4

Browse files
Merge pull request #38 from developerdizzle/HOC
WIP - Version 2 - HOC
2 parents f7c96fe + b8d9870 commit 9e4a3f4

32 files changed

+1278
-1133
lines changed

.babelrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"presets": [
3+
"es2015",
4+
"stage-0",
5+
"react"
6+
]
7+
}

.travis.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
language: node_js
2-
node_js: stable
2+
node_js: stable
3+
after_success:
4+
bash ./deploy-to-gh-pages.sh
5+
env:
6+
global:
7+
secure: eel7PQWWJmM2gyxTCiUzv/4GYfDfKqrPTcEZOFYGgF0JkdgAqwowvnbw9B8Oexwhp8z/4hPwZNaeZnOAUlUekTJhpMItRcw6egyPyRxzgw2Uk1JC5JU6WVZdjjqQ4GJ+N6Spt56HGiEnTBtVAo2z1deah6s2Z9ZFnc/wqfz/Y/tE5NWE1ePD3cfqnf35yZ2jQkaOMPUS36inYRm+Fjc3IdCEH0OE/IsKYW00MLWlCyN/OkhElMW9kcjpzfpfdSjsyWNnAZF9BZykD053bh+R8gkKkFdyHzkA/w5wQoXAkRkz7ONkDOYXHNQK4VFwT0sl8+WU2tccmKFM9YGxnwLcBCF4ZUxoUNGaWsZsF9xlDZ0ZaV7/ySYyqpFZtfJvv42R1bx7wbIz8PVWqL2/Tl+HMU47X+L6ukDz3yZPFI/3Dcr0ksMU6/YmQR3yoBlTRyX7eJKjO3hiDHys1lFEsA6gCh9IU43a00msAHXOBJ171OL0SDn5qbeUhSS2LRnwXTBh5HZ9b5o7Zrj9nFtaL450kAXBoE5aulI+hAixce7tPNL7fLs+/WRKnYwxLyrjQ7aiv3NVJbZc3RkdheGVB8Wo15mAZZ6cJKCjChfJTPpIM92ZrFFi45dOa8KhVwll1+vqMv6P0fWXHXvBIItPMrGbMrGz0vzUvpePiEMhX2MjtO8=

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2015 Dizzle
3+
Copyright (c) 2017 Dizzle
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,102 @@
11
# [react-virtual-list](http://developerdizzle.github.io/react-virtual-list/) [![Build Status](https://travis-ci.org/developerdizzle/react-virtual-list.svg?branch=master)](https://travis-ci.org/developerdizzle/react-virtual-list)
22

3-
Super simple virtualized list [React](https://github.com/facebook/react) component
3+
Super simple virtualized list [higher-order component](https://facebook.github.io/react/docs/higher-order-components.html) for [React](https://github.com/facebook/react) version `^15.0.0`.
44

55
[Check out the demo here](http://developerdizzle.github.io/react-virtual-list)
66

7-
This React component allows you to display a large list of fixed-height items in your document, while only rendering the items visible in the viewport. This allows a large list to be rendered with much fewer DOM elements.
7+
`react-virtual-list` allows you to display a large list of fixed-height items, while only rendering the items visible on the screen. This allows a large list to be rendered with much fewer DOM elements.
8+
9+
### Some other benefits:
10+
* Zero dependencies
11+
* Small - `~4.2k` gzipped & minified, `~4.9k` minified [http://i.imgur.com/DxRCuLv.png](http://i.imgur.com/DxRCuLv.png)
12+
* Decent performance - demo page almost always stays over 60fps [http://i.imgur.com/CHVCK9x.png](http://i.imgur.com/CHVCK9x.png)
13+
* Keeps your components separate - as a higher-order component
14+
* Gives you control - doesn't force any particular markup, but gives you the necessary styles and data to use.
15+
16+
## Legacy
17+
18+
If you're looking for documentation on version 1, supporting React `~0.13.x`, it's [here](README.v1.md).
819

920
## Installation
1021

11-
You can use NPM to install react-virtual-list:
22+
You can use [npm](https://npmjs.org) to install [react-virtual-list](https://www.npmjs.com/package/react-virtual-list).
1223

1324
```console
14-
$ npm install react-virtual-list --save
25+
> npm install react-virtual-list --save
1526
```
1627

1728
## Usage
1829

19-
The `./dist/VirtualList.js` module exports a single React component.
30+
The `./lib/VirtualList.js` module exports a single, ES5-compatible, CommonJS-accessible, component factory.
2031

32+
```js
33+
import VirtualList from 'react-virtual-list';
2134
```
22-
var VirtualList = require('react-virtual-list');
35+
36+
Your inner list component uses the `virtual` property to render the visible items, and set a style to set the overall list height and padding.
37+
38+
```js
39+
const MyList = ({
40+
virtual,
41+
itemHeight,
42+
}) => (
43+
<ul style={virtual.style}>
44+
{virtual.items.map(item => (
45+
<li key={`item_${item.id}`} style={{height: itemHeight}}>
46+
Lorem ipsum dolor sit amet
47+
</li>
48+
))}
49+
</ul>
50+
);
2351
```
2452

25-
#### JSX
53+
**Note:** You should set [keys](https://facebook.github.io/react/docs/lists-and-keys.html) on your list items.
2654

55+
Create the virtualized component.
56+
57+
```js
58+
const MyVirtualList = VirtualList()(MyList);
2759
```
28-
<VirtualList items={this.props.items} renderItem={this.renderItem} itemHeight={this.props.itemHeight} />
60+
61+
Write the JSX for the virtualized component with the necessary [properties](#properties).
62+
63+
```js
64+
<MyVirtualList
65+
items={myBigListOfItems}
66+
itemHeight={100}
67+
/>
2968
```
3069

31-
#### Properties
70+
#### Options
3271

33-
* `items` the full array of list items. Only the visible subset of these will be rendered.
34-
* `renderItem` a function to render a single item, passed as argument `item`. Must return a single React element (`React.createElement(...)`)
35-
* `itemHeight` the height in pixels of a single item. **You must have a CSS rule that sets the height of each list item to this value.**
36-
* `container` the scrollable element that contains the list. Defaults to `window`. Use this if you have a list inside an element with `overflow: scroll`.
37-
* `tagName` the tagName for the root element that surrounds the items rendered by renderItem. Defaults to `div`. Use this if you want to render a list with `ul` and `li`, or any other elements.
38-
* `scrollDelay` the delay in milliseconds after scroll to recalculate. Defaults to `0`. Can be used to throttle recalculation.
39-
* `itemBuffer` the number of items that should be rendered before and after the visible viewport. Defaults to `0`.
40-
41-
Any other properties set on `VirtualList`, such as `className`, will be reflected on the component's root element.
72+
Options are used before the virtualized component can be created. This means that if you need to change an option after the initial render, you will need to recreate the virtualized component.
4273

43-
#### Functions
74+
```js
75+
const options = {
76+
container: this.refs.container
77+
};
4478

45-
* `visibleItems` the currently visible array of items. Can be used to figure out which items are in the viewport. Eg: `var items = this.refs.list.visibleItems()`
79+
const MyVirtualList = VirtualList(options)(MyList);
80+
```
4681

47-
#### Example Usage
82+
Name | Type | Default | Description
83+
--- | --- | --- | ---
84+
`container` | DOM Element | window | Scrollable element that contains the list. Use this if you have a list inside an element with `overflow: scroll`.
4885

49-
Check out [https://github.com/developerdizzle/react-virtual-list/blob/gh-pages/App.jsx](https://github.com/developerdizzle/react-virtual-list/blob/gh-pages/App.jsx) for the example used in the demo.
86+
#### Properties
5087

51-
## Tests
88+
These properties and any others set on your virtual component, such as `className`, will be passed down to the inner component.
5289

53-
Use `npm test` to run the tests using [jasmine-node](https://github.com/mhevery/jasmine-node). Currently only the math calculations are tested. Hoping to add some DOM tests as well.
90+
Name | Type | Default | Description
91+
--- | --- | --- | ---
92+
`items` | Array | - | Full array of list items. Only the visible subset of these will be rendered.
93+
`itemHeight` | Number | - | Height in pixels of a single item. **You must have a CSS rule that sets the height of each list item to this value.**
94+
`itemBuffer` | Number | 0 | Number of items that should be rendered before and after the visible viewport. Try using this if you have a complex list that suffers from a bit of lag when scrolling.
5495

55-
## To Do
96+
#### Example Usage
97+
98+
Check out [demo/src/app.js](demo/src/app.js) and [demo/src/ConfigurableExample.js](demo/src/ConfigurableExample.js) for the example used in the [demo](http://developerdizzle.github.io/react-virtual-list).
99+
100+
## Tests
56101

57-
* ES6/2015
58-
* [Known issue with mobile scroll event](https://github.com/developerdizzle/react-virtual-list/issues/1)
102+
Use `npm test` to run the tests using [Jest](https://github.com/facebook/jest). Not everything is currently tested yet!

README.v1.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# [react-virtual-list](http://developerdizzle.github.io/react-virtual-list/) [![Build Status](https://travis-ci.org/developerdizzle/react-virtual-list.svg?branch=master)](https://travis-ci.org/developerdizzle/react-virtual-list)
2+
# Legacy (version 1)
3+
4+
Super simple virtualized list [React](https://github.com/facebook/react) component
5+
6+
[Check out the demo here](http://developerdizzle.github.io/react-virtual-list)
7+
8+
This React component allows you to display a large list of fixed-height items in your document, while only rendering the items visible in the viewport. This allows a large list to be rendered with much fewer DOM elements.
9+
10+
## Installation
11+
12+
You can use NPM to install react-virtual-list:
13+
14+
```console
15+
$ npm install react-virtual-list --save
16+
```
17+
18+
## Usage
19+
20+
The `./dist/VirtualList.js` module exports a single React component.
21+
22+
```
23+
var VirtualList = require('react-virtual-list');
24+
```
25+
26+
#### JSX
27+
28+
```
29+
<VirtualList items={this.props.items} renderItem={this.renderItem} itemHeight={this.props.itemHeight} />
30+
```
31+
32+
#### Properties
33+
34+
* `items` the full array of list items. Only the visible subset of these will be rendered.
35+
* `renderItem` a function to render a single item, passed as argument `item`. Must return a single React element (`React.createElement(...)`)
36+
* `itemHeight` the height in pixels of a single item. **You must have a CSS rule that sets the height of each list item to this value.**
37+
* `container` the scrollable element that contains the list. Defaults to `window`. Use this if you have a list inside an element with `overflow: scroll`.
38+
* `tagName` the tagName for the root element that surrounds the items rendered by renderItem. Defaults to `div`. Use this if you want to render a list with `ul` and `li`, or any other elements.
39+
* `scrollDelay` the delay in milliseconds after scroll to recalculate. Defaults to `0`. Can be used to throttle recalculation.
40+
* `itemBuffer` the number of items that should be rendered before and after the visible viewport. Defaults to `0`.
41+
42+
Any other properties set on `VirtualList`, such as `className`, will be reflected on the component's root element.
43+
44+
#### Functions
45+
46+
* `visibleItems` the currently visible array of items. Can be used to figure out which items are in the viewport. Eg: `var items = this.refs.list.visibleItems()`
47+
48+
#### Example Usage
49+
50+
Check out [https://github.com/developerdizzle/react-virtual-list/blob/gh-pages/App.jsx](https://github.com/developerdizzle/react-virtual-list/blob/gh-pages/App.jsx) for the example used in the demo.
51+
52+
## Tests
53+
54+
Use `npm test` to run the tests using [jasmine-node](https://github.com/mhevery/jasmine-node). Currently only the math calculations are tested. Hoping to add some DOM tests as well.
55+
56+
## To Do
57+
58+
* ES6/2015
59+
* [Known issue with mobile scroll event](https://github.com/developerdizzle/react-virtual-list/issues/1)

demo/src/ConfigurableExample.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import React, { PureComponent, PropTypes } from 'react';
2+
import VirtualList from '../../src/VirtualList';
3+
4+
const makeItem = (i) => ({
5+
id: i,
6+
title: `Media heading #${i+1}`,
7+
text: 'Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis.',
8+
});
9+
10+
const ConfigurableExample = (MyList) => {
11+
return class MyConfigurableList extends PureComponent {
12+
constructor() {
13+
super();
14+
15+
const defaultItemCount = 100000;
16+
17+
const items = [];
18+
19+
for (let i = 0; i < defaultItemCount; i++) {
20+
items[i] = makeItem(i);
21+
}
22+
23+
const state = {
24+
itemHeight: 100,
25+
itemCount: defaultItemCount,
26+
items: items,
27+
contained: false,
28+
containerHeight: 250,
29+
itemBuffer: 0,
30+
};
31+
32+
this.state = state;
33+
34+
this.update = this.update.bind(this);
35+
36+
this.MyVirtualList = VirtualList()(MyList);
37+
};
38+
39+
update() {
40+
console.log('update');
41+
42+
const items = [];
43+
const itemCount = parseInt(this.refs.itemCount.value, 10);
44+
45+
for (var i = 0; i < itemCount; i++) {
46+
items[i] = makeItem(i);
47+
}
48+
49+
const contained = this.refs.contained.checked;
50+
51+
const state = {
52+
itemHeight: parseInt(this.refs.itemHeight.value, 10),
53+
itemCount: itemCount,
54+
items: items,
55+
contained: contained,
56+
container: this.refs.container,
57+
containerHeight: parseInt(this.refs.containerHeight.value, 10),
58+
itemBuffer: parseInt(this.refs.itemBuffer.value, 10),
59+
};
60+
61+
if (state.contained !== this.state.contained) {
62+
const options = {
63+
container: state.contained ? state.container : window,
64+
};
65+
66+
this.MyVirtualList = VirtualList(options)(MyList);
67+
}
68+
69+
this.setState(state);
70+
};
71+
72+
render() {
73+
const MyVirtualList = this.MyVirtualList;
74+
75+
return (
76+
<div>
77+
<div role="form" className="form-horizontal">
78+
<div className="form-group">
79+
<label className="col-xs-6 col-sm-2" htmlFor="contained">Contained</label>
80+
<div className="col-xs-6 col-sm-4">
81+
<input onChange={this.update} className="form-control" type="checkbox" checked ={this.state.contained} id="contained" ref="contained" />
82+
</div>
83+
<label className="col-xs-6 col-sm-2" htmlFor="containerHeight">Container Height</label>
84+
<div className="col-xs-6 col-sm-4">
85+
<input onChange={this.update} className="form-control" type="number" min="0" max="10000" value={this.state.containerHeight} id="containerHeight" ref="containerHeight" />
86+
</div>
87+
</div>
88+
<div className="form-group">
89+
<label className="col-xs-6 col-sm-2" htmlFor="itemHeight">Item Height</label>
90+
<div className="col-xs-6 col-sm-4">
91+
<input onChange={this.update} className="form-control" type="number" min="0" value={this.state.itemHeight} id="itemHeight" ref="itemHeight" />
92+
</div>
93+
<label className="col-xs-6 col-sm-2" htmlFor="itemCount">Item Count</label>
94+
<div className="col-xs-6 col-sm-4">
95+
<input onChange={this.update} className="form-control" type="number" min="0" value={this.state.itemCount} id="itemCount" ref="itemCount" />
96+
</div>
97+
</div>
98+
<div className="form-group">
99+
<label className="col-xs-6 col-sm-2" htmlFor="scrollDelay">Item Buffer</label>
100+
<div className="col-xs-6 col-sm-4">
101+
<input onChange={this.update} className="form-control" type="number" min="0" value={this.state.itemBuffer} id="itemBuffer" ref="itemBuffer" />
102+
</div>
103+
</div>
104+
</div>
105+
<div className="row">
106+
<div className="col-xs-12" id="container" ref="container" style={this.state.contained ? { overflow: 'scroll', height: this.state.containerHeight } : {}}>
107+
<MyVirtualList
108+
items={this.state.items}
109+
itemBuffer={this.state.itemBuffer}
110+
itemHeight={this.state.itemHeight}
111+
/>
112+
</div>
113+
</div>
114+
</div>
115+
);
116+
};
117+
};
118+
};
119+
120+
export default ConfigurableExample;

demo/src/app.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from 'react';
2+
import { render } from 'react-dom';
3+
import ConfigurableExample from './ConfigurableExample';
4+
5+
require('file?name=[name].[ext]!./index.html');
6+
7+
const MyList = ({
8+
virtual,
9+
itemHeight,
10+
}) => (
11+
<ul className="media-list list-group" style={virtual.style}>
12+
{virtual.items.map((item) => (
13+
<li key={`item${item.id}`} className="list-group-item" style={{height: itemHeight }}>
14+
<div className="media-left">
15+
<img className="media-object" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnMvPjxyZWN0IHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjEzLjQ2ODc1IiB5PSIzMiIgc3R5bGU9ImZpbGw6I0FBQUFBQTtmb250LXdlaWdodDpib2xkO2ZvbnQtZmFtaWx5OkFyaWFsLCBIZWx2ZXRpY2EsIE9wZW4gU2Fucywgc2Fucy1zZXJpZiwgbW9ub3NwYWNlO2ZvbnQtc2l6ZToxMHB0O2RvbWluYW50LWJhc2VsaW5lOmNlbnRyYWwiPjY0eDY0PC90ZXh0PjwvZz48L3N2Zz4=" />
16+
</div>
17+
<div className="media-body">
18+
<h4 className="media-heading">{item.title}</h4>
19+
<p>{item.text}</p>
20+
</div>
21+
</li>
22+
))}
23+
</ul>
24+
);
25+
26+
const MyConfigurableExample = ConfigurableExample(MyList);
27+
28+
render(
29+
<MyConfigurableExample />,
30+
document.getElementById('app')
31+
);
32+

0 commit comments

Comments
 (0)