Skip to content

Commit b9d113a

Browse files
author
Davide Curletti
committed
Adds dynamic classes and child props
1 parent 3f6971c commit b9d113a

5 files changed

+106
-31
lines changed

Readme.md

+10-6
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ npm install redux-infinite-scroll --save
1717

1818
## Usage
1919

20-
In order to use it in your React app, simply import it and follow the example below. The component expects the items
21-
prop to receive an array of React components that it then renders to the DOM. The `loadMore` prop
22-
expects a function that updates the Redux store with more items and therefore causes React to re-render the component.
20+
In order to use it in your React app, simply import it and follow the example below. The component expects to receive
21+
child elements that it then injects into the DOM. The `loadMore` prop expects a function that requests for more
22+
items to be loaded once the container/window has reached the bottom `threshold`. If there are no more items left to
23+
be passed to the component, make sure to set the `hasMore` prop to be `false`. **Important** If you are using
24+
an element as the scrollable component, rather than the window, you MUST pass a fixed height to the `containerHeight`
25+
prop.
2326

2427
##### ES6 format
2528

@@ -94,14 +97,15 @@ function chatReducer(state=initialState, action=undefined) {
9497
| elementIsScrollable | bool | no | true | Defines whether the div will have a fixed height and listens to the div's overflow event or instead have a non-fixed height and listen to the window scroll event
9598
| containerHeight | integer or string | no | '100%' | Sets an inline style on the height of the topmost div.
9699
| threshold | integer | no | 100 | The number of pixels
97-
| hasMore | bool | no | true | Whether there are more items waiting to be displayed
100+
| hasMore | bool | no | true | Whether there are more items waiting to be displayed. Set this to false once all of the items have been passed down to either `items` or `children`.
98101
| loadingMore | bool | no |false| A prop that should be set to `true` by the parent component whenever the `loadMore` function gets invoked, and then toggled to `false` once that function has finished updating the `items` prop.
99102
| loader | any | no| Loading... | The value of this prop gets injected as the last element of the parent div when `hasMore` `loadingMore` and `showLoader` are all `true`.
100-
| showLoader | bool | true | | Whether to show the loader when the `loadingMore` property is `true`
103+
| showLoader | bool | false | true | Whether to show the loader when the `loadingMore` property is `true`
101104
| loadMore | function | yes |undefined| The function is called when the component has reached the `threshold` and `hasMore` is true.
102-
| items | array |yes|undefined| The array of elements waiting to be rendered. Normally each item in the array is a React component.
103105
| holderType | string |no|div| The type the loader is rendered as, could be `ul`, `dl`, etc.
104106
| className | string |no|''| Any additional classes to be added to the holder.
107+
| items | array || Immutable List |no|[]| The array of elements waiting to be rendered. Use either this or `children`. **Deprecated.**
108+
| children | array || Immutable List |no| [] | The array of elements waiting to be rendered. Use either this or `items`.
105109

106110
## Credits
107111

dist/redux-infinite-scroll.min.js

+22-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/ReduxInfiniteScroll.js

+33-10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ var _reactDom = require('react-dom');
1414

1515
var _reactDom2 = _interopRequireDefault(_reactDom);
1616

17+
var _reactImmutableProptypes = require('react-immutable-proptypes');
18+
19+
var _reactImmutableProptypes2 = _interopRequireDefault(_reactImmutableProptypes);
20+
1721
var _DOMPositionUtils = require('./Utilities/DOMPositionUtils');
1822

1923
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -87,17 +91,18 @@ var ReduxInfiniteScroll = function (_Component) {
8791
var _this2 = this;
8892

8993
// This is to prevent the upcoming logic from toggling a load more before
90-
// redux has passed any data to the component
94+
// any data has been passed to the component
9195
if (this.props.items <= 0) return;
9296

97+
// Need to find better way around this setTimeout
9398
setTimeout(function () {
9499
var bottomPosition = _this2.props.elementIsScrollable ? _this2._elScrollListener() : _this2._windowScrollListener();
95100

96101
if (bottomPosition < Number(_this2.props.threshold)) {
97102
_this2.detachScrollListener();
98103
_this2.props.loadMore();
99104
}
100-
}, 0);
105+
});
101106
}
102107
}, {
103108
key: 'detachScrollListener',
@@ -106,6 +111,13 @@ var ReduxInfiniteScroll = function (_Component) {
106111
el.removeEventListener('scroll', this.scrollFunction, true);
107112
el.removeEventListener('resize', this.scrollFunction, true);
108113
}
114+
}, {
115+
key: '_renderOptions',
116+
value: function _renderOptions() {
117+
var allItems = this.props.children.concat(this.props.items);
118+
119+
return [allItems, this.renderLoader()];
120+
}
109121
}, {
110122
key: 'componentWillUnmount',
111123
value: function componentWillUnmount() {
@@ -116,17 +128,23 @@ var ReduxInfiniteScroll = function (_Component) {
116128
value: function renderLoader() {
117129
return this.props.loadingMore && this.props.showLoader ? this.props.loader : undefined;
118130
}
131+
}, {
132+
key: '_assignHolderClass',
133+
value: function _assignHolderClass() {
134+
var additionalClass = void 0;
135+
additionalClass = typeof this.props.className === 'function' ? this.props.className() : this.props.className;
136+
137+
return 'redux-infinite-scroll ' + additionalClass;
138+
}
119139
}, {
120140
key: 'render',
121141
value: function render() {
122142
var Holder = this.props.holderType;
143+
123144
return _react2.default.createElement(
124145
Holder,
125-
{ className: 'rs-infinite-scroll', style: { height: this.props.containerHeight } },
126-
this.props.items.map(function (item, i) {
127-
return item;
128-
}),
129-
this.renderLoader()
146+
{ className: this._assignHolderClass(), style: { height: this.props.containerHeight } },
147+
this._renderOptions()
130148
);
131149
}
132150
}]);
@@ -146,11 +164,14 @@ ReduxInfiniteScroll.propTypes = {
146164
loader: _react2.default.PropTypes.any,
147165
showLoader: _react2.default.PropTypes.bool,
148166
loadMore: _react2.default.PropTypes.func.isRequired,
149-
items: _react2.default.PropTypes.array.isRequired,
150-
holderType: _react2.default.PropTypes.string
167+
items: _react2.default.PropTypes.oneOfType([_reactImmutableProptypes2.default.list, _react2.default.PropTypes.array]),
168+
children: _react2.default.PropTypes.oneOfType([_reactImmutableProptypes2.default.list, _react2.default.PropTypes.array]),
169+
holderType: _react2.default.PropTypes.string,
170+
className: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.func])
151171
};
152172

153173
ReduxInfiniteScroll.defaultProps = {
174+
className: '',
154175
elementIsScrollable: true,
155176
containerHeight: '100%',
156177
threshold: 100,
@@ -162,5 +183,7 @@ ReduxInfiniteScroll.defaultProps = {
162183
'Loading...'
163184
),
164185
showLoader: true,
165-
holderType: 'div'
186+
holderType: 'div',
187+
children: [],
188+
items: []
166189
};

package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "redux-infinite-scroll",
3-
"version": "1.0.2",
3+
"version": "1.0.4",
44
"description": "React infinite scroll component designed for a Redux data-flow.",
55
"main": "lib/ReduxInfiniteScroll.js",
66
"scripts": {
@@ -50,8 +50,10 @@
5050
"webpack-hot-middleware": "^2.6.0"
5151
},
5252
"dependencies": {
53+
"immutable": "^3.7.6",
54+
"lodash": "~3.1.0",
5355
"react": "^0.14.6",
5456
"react-dom": "^0.14.6",
55-
"lodash": "~3.1.0"
57+
"react-immutable-proptypes": "^1.7.0"
5658
}
5759
}

src/ReduxInfiniteScroll.jsx

+37-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, { Component } from 'react';
22
import ReactDOM from 'react-dom';
33

4+
import ImmutablePropTypes from 'react-immutable-proptypes';
5+
46
import {topPosition} from './Utilities/DOMPositionUtils';
57

68
export default class ReduxInfiniteScroll extends Component {
@@ -51,17 +53,18 @@ export default class ReduxInfiniteScroll extends Component {
5153

5254
scrollListener() {
5355
// This is to prevent the upcoming logic from toggling a load more before
54-
// redux has passed any data to the component
56+
// any data has been passed to the component
5557
if (this.props.items <= 0) return;
5658

59+
// Need to find better way around this setTimeout
5760
setTimeout(() => {
5861
let bottomPosition = this.props.elementIsScrollable ? this._elScrollListener() : this._windowScrollListener();
5962

6063
if (bottomPosition < Number(this.props.threshold)) {
6164
this.detachScrollListener();
6265
this.props.loadMore();
6366
}
64-
}, 0);
67+
});
6568
}
6669

6770
detachScrollListener () {
@@ -70,6 +73,12 @@ export default class ReduxInfiniteScroll extends Component {
7073
el.removeEventListener('resize', this.scrollFunction, true);
7174
}
7275

76+
_renderOptions() {
77+
const allItems = this.props.children.concat(this.props.items);
78+
79+
return [allItems, this.renderLoader()];
80+
}
81+
7382
componentWillUnmount () {
7483
this.detachScrollListener();
7584
}
@@ -78,17 +87,20 @@ export default class ReduxInfiniteScroll extends Component {
7887
return (this.props.loadingMore && this.props.showLoader) ? this.props.loader : undefined;
7988
}
8089

90+
_assignHolderClass() {
91+
let additionalClass;
92+
additionalClass = (typeof this.props.className === 'function') ? this.props.className() : this.props.className;
93+
94+
return 'redux-infinite-scroll ' + additionalClass;
95+
}
96+
8197
render () {
8298
const Holder = this.props.holderType;
83-
const className = "rs-infinite-scroll " + this.props.className;
8499

85100
return (
86-
<Holder className={ className } style={{height: this.props.containerHeight}}>
87-
{this.props.items.map((item, i) => {
88-
return item;
89-
})}
90-
{this.renderLoader()}
91-
</Holder>
101+
<Holder className={ this._assignHolderClass() } style={{height: this.props.containerHeight}}>
102+
{this._renderOptions()}
103+
</Holder>
92104
)
93105
}
94106
}
@@ -105,8 +117,19 @@ ReduxInfiniteScroll.propTypes = {
105117
loader: React.PropTypes.any,
106118
showLoader: React.PropTypes.bool,
107119
loadMore: React.PropTypes.func.isRequired,
108-
items: React.PropTypes.array.isRequired,
109-
holderType: React.PropTypes.string
120+
items: React.PropTypes.oneOfType([
121+
ImmutablePropTypes.list,
122+
React.PropTypes.array
123+
]),
124+
children: React.PropTypes.oneOfType([
125+
ImmutablePropTypes.list,
126+
React.PropTypes.array
127+
]),
128+
holderType: React.PropTypes.string,
129+
className: React.PropTypes.oneOfType([
130+
React.PropTypes.string,
131+
React.PropTypes.func
132+
])
110133
};
111134

112135
ReduxInfiniteScroll.defaultProps = {
@@ -118,5 +141,7 @@ ReduxInfiniteScroll.defaultProps = {
118141
loadingMore: false,
119142
loader: <div style={{textAlign: 'center'}}>Loading...</div>,
120143
showLoader: true,
121-
holderType: 'div'
144+
holderType: 'div',
145+
children: [],
146+
items: []
122147
};

0 commit comments

Comments
 (0)