Skip to content

Pass first last indexes / use updated react lifecycle methods / use state instead class properties #78

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 76 additions & 67 deletions lib/VirtualList.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,120 +46,129 @@ var VirtualList = function VirtualList(options) {
var _class, _temp;

return _temp = _class = function (_PureComponent) {
_inherits(vlist, _PureComponent);
_inherits(VList, _PureComponent);

function vlist(props) {
_classCallCheck(this, vlist);
function VList(props) {
_classCallCheck(this, VList);

var _this = _possibleConstructorReturn(this, (vlist.__proto__ || Object.getPrototypeOf(vlist)).call(this, props));
var _this = _possibleConstructorReturn(this, (VList.__proto__ || Object.getPrototypeOf(VList)).call(this, props));

_this._isMounted = false;

_this.refreshState = function () {
if (!_this._isMounted) {
return;
}

var _this$props = _this.props,
itemHeight = _this$props.itemHeight,
items = _this$props.items,
itemBuffer = _this$props.itemBuffer;
var _this$state = _this.state,
domNode = _this$state.domNode,
container = _this$state.options.container,
firstItemIndex = _this$state.firstItemIndex,
lastItemIndex = _this$state.lastItemIndex;

var state = VList.setStateIfNeeded(domNode, container, items, itemHeight, itemBuffer, firstItemIndex, lastItemIndex);

_this.options = _extends({
container: typeof window !== 'undefined' ? window : undefined
}, options);
_this.setState(state);
};

_this.state = {
firstItemIndex: 0,
lastItemIndex: -1
lastItemIndex: -1,
options: _extends({
container: typeof window !== 'undefined' ? window : undefined
}, options)
};

// initialState allows us to set the first/lastItemIndex (useful for server-rendering)
if (options && options.initialState) {
_this.state = _extends({}, _this.state, options.initialState);
}

_this.refreshState = _this.refreshState.bind(_this);

// if requestAnimationFrame is available, use it to throttle refreshState
if (typeof window !== 'undefined' && 'requestAnimationFrame' in window) {
_this.refreshState = (0, _throttleWithRAF2.default)(_this.refreshState);
}
return _this;
}

_createClass(vlist, [{
key: 'setStateIfNeeded',
value: function setStateIfNeeded(list, container, items, itemHeight, itemBuffer) {
// get first and lastItemIndex
var state = (0, _getVisibleItemBounds2.default)(list, container, items, itemHeight, itemBuffer);

if (state === undefined) {
return;
}

if (state.firstItemIndex > state.lastItemIndex) {
return;
}

if (state.firstItemIndex !== this.state.firstItemIndex || state.lastItemIndex !== this.state.lastItemIndex) {
this.setState(state);
}
}
}, {
key: 'refreshState',
value: function refreshState() {
if (!this._isMounted) {
return;
}

var _props = this.props,
itemHeight = _props.itemHeight,
items = _props.items,
itemBuffer = _props.itemBuffer;
_createClass(VList, [{
key: 'componentDidMount',
value: function componentDidMount() {
var container = this.state.options.container;


this.setStateIfNeeded(this.domNode, this.options.container, items, itemHeight, itemBuffer);
}
}, {
key: 'componentWillMount',
value: function componentWillMount() {
this._isMounted = true;
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {

// cache the DOM node
this.domNode = _reactDom2.default.findDOMNode(this);
this.setState({ domNode: _reactDom2.default.findDOMNode(this) });

// we need to refreshState because we didn't have access to the DOM node before
this.refreshState();

// add events
this.options.container.addEventListener('scroll', this.refreshState);
this.options.container.addEventListener('resize', this.refreshState);
container.addEventListener('scroll', this.refreshState);
container.addEventListener('resize', this.refreshState);
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
var container = this.state.options.container;


this._isMounted = false;

// remove events
this.options.container.removeEventListener('scroll', this.refreshState);
this.options.container.removeEventListener('resize', this.refreshState);
container.removeEventListener('scroll', this.refreshState);
container.removeEventListener('resize', this.refreshState);
}
}, {
key: 'componentWillReceiveProps',
key: 'render',
value: function render() {
return _react2.default.createElement(InnerComponent, _extends({}, this.props, mapVirtualToProps(this.props, this.state)));
}
}], [{
key: 'setStateIfNeeded',
value: function setStateIfNeeded(list, container, items, itemHeight, itemBuffer, firstItemIndex, lastItemIndex) {
// get first and lastItemIndex
var state = (0, _getVisibleItemBounds2.default)(list, container, items, itemHeight, itemBuffer);

if (state === undefined) {
return null;
}

if (state.firstItemIndex > state.lastItemIndex) {
return null;
}

if (state.firstItemIndex !== firstItemIndex || state.lastItemIndex !== lastItemIndex) {
return state;
}
}

// if props change, just assume we have to recalculate
value: function componentWillReceiveProps(nextProps) {

}, {
key: 'getDerivedStateFromProps',
value: function getDerivedStateFromProps(nextProps, nextState) {
var itemHeight = nextProps.itemHeight,
items = nextProps.items,
itemBuffer = nextProps.itemBuffer;
var domNode = nextState.domNode,
container = nextState.options.container,
firstItemIndex = nextState.firstItemIndex,
lastItemIndex = nextState.lastItemIndex;


this.setStateIfNeeded(this.domNode, this.options.container, items, itemHeight, itemBuffer);
}
}, {
key: 'render',
value: function render() {
return _react2.default.createElement(InnerComponent, _extends({}, this.props, mapVirtualToProps(this.props, this.state)));
var state = VList.setStateIfNeeded(domNode, container, items, itemHeight, itemBuffer, firstItemIndex, lastItemIndex);

if (state === undefined) {
return null;
}

return state;
}
}]);

return vlist;
return VList;
}(_react.PureComponent), _class.propTypes = {
items: _propTypes2.default.array.isRequired,
itemHeight: _propTypes2.default.number.isRequired,
Expand Down
2 changes: 2 additions & 0 deletions lib/utils/defaultMapVirtualToProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ var defaultMapToVirtualProps = function defaultMapToVirtualProps(_ref, _ref2) {
return {
virtual: {
items: visibleItems,
firstItemIndex: firstItemIndex,
lastItemIndex: lastItemIndex,
style: {
height: height,
paddingTop: paddingTop,
Expand Down
9 changes: 4 additions & 5 deletions lib/utils/getVisibleItemBounds.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de

var getVisibleItemBounds = function getVisibleItemBounds(list, container, items, itemHeight, itemBuffer) {
// early return if we can't calculate
if (!container) return undefined;
if (!itemHeight) return undefined;
if (!items) return undefined;
if (items.length === 0) return undefined;
if (!container || !itemHeight || !items || items.length === 0) {
return null;
}

// what the user can see
var innerHeight = container.innerHeight,
Expand All @@ -28,7 +27,7 @@ var getVisibleItemBounds = function getVisibleItemBounds(list, container, items,

var viewHeight = innerHeight || clientHeight; // how many pixels are visible

if (!viewHeight) return undefined;
if (!viewHeight) return null;

var viewTop = (0, _getElementTop2.default)(container); // top y-coordinate of viewport inside container
var viewBottom = viewTop + viewHeight;
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"webpack": "^1.13.3"
},
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0",
"react-dom": "^15.0.0 || ^16.0.0"
"react": "^16.0.0",
"react-dom": "^16.0.0"
}
}
Loading