From 097f374296b4b13f4351351138d394612c1961f6 Mon Sep 17 00:00:00 2001 From: chengong Date: Mon, 26 Nov 2018 11:36:28 +0800 Subject: [PATCH] fix: you should check hasMore before loadMore --- .gitignore | 1 + dist/InfiniteScroll.js | 385 ----------------------------------------- src/InfiniteScroll.js | 2 +- yarn.lock | 120 ++++++++----- 4 files changed, 81 insertions(+), 427 deletions(-) delete mode 100644 dist/InfiniteScroll.js diff --git a/.gitignore b/.gitignore index 19880bb..417ba04 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ npm-debug.log .idea .nyc_output coverage +dist/ diff --git a/dist/InfiniteScroll.js b/dist/InfiniteScroll.js deleted file mode 100644 index d7faadd..0000000 --- a/dist/InfiniteScroll.js +++ /dev/null @@ -1,385 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true, -}); - -var _createClass = (function() { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ('value' in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - return function(Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; -})(); - -var _react = require('react'); - -var _react2 = _interopRequireDefault(_react); - -var _propTypes = require('prop-types'); - -var _propTypes2 = _interopRequireDefault(_propTypes); - -function _interopRequireDefault(obj) { - return obj && obj.__esModule ? obj : { default: obj }; -} - -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; -} - -function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError('Cannot call a class as a function'); - } -} - -function _possibleConstructorReturn(self, call) { - if (!self) { - throw new ReferenceError( - "this hasn't been initialised - super() hasn't been called", - ); - } - return call && (typeof call === 'object' || typeof call === 'function') - ? call - : self; -} - -function _inherits(subClass, superClass) { - if (typeof superClass !== 'function' && superClass !== null) { - throw new TypeError( - 'Super expression must either be null or a function, not ' + - typeof superClass, - ); - } - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true, - }, - }); - if (superClass) - Object.setPrototypeOf - ? Object.setPrototypeOf(subClass, superClass) - : (subClass.__proto__ = superClass); -} - -var InfiniteScroll = (function(_Component) { - _inherits(InfiniteScroll, _Component); - - function InfiniteScroll(props) { - _classCallCheck(this, InfiniteScroll); - - var _this = _possibleConstructorReturn( - this, - (InfiniteScroll.__proto__ || Object.getPrototypeOf(InfiniteScroll)).call( - this, - props, - ), - ); - - _this.scrollListener = _this.scrollListener.bind(_this); - return _this; - } - - _createClass(InfiniteScroll, [ - { - key: 'componentDidMount', - value: function componentDidMount() { - this.pageLoaded = this.props.pageStart; - this.attachScrollListener(); - }, - }, - { - key: 'componentDidUpdate', - value: function componentDidUpdate() { - this.attachScrollListener(); - }, - }, - { - key: 'componentWillUnmount', - value: function componentWillUnmount() { - this.detachScrollListener(); - this.detachMousewheelListener(); - }, - - // Set a defaut loader for all your `InfiniteScroll` components - }, - { - key: 'setDefaultLoader', - value: function setDefaultLoader(loader) { - this.defaultLoader = loader; - }, - }, - { - key: 'detachMousewheelListener', - value: function detachMousewheelListener() { - var scrollEl = window; - if (this.props.useWindow === false) { - scrollEl = this.scrollComponent.parentNode; - } - - scrollEl.removeEventListener( - 'mousewheel', - this.mousewheelListener, - this.props.useCapture, - ); - }, - }, - { - key: 'detachScrollListener', - value: function detachScrollListener() { - var scrollEl = window; - if (this.props.useWindow === false) { - scrollEl = this.getParentElement(this.scrollComponent); - } - - scrollEl.removeEventListener( - 'scroll', - this.scrollListener, - this.props.useCapture, - ); - scrollEl.removeEventListener( - 'resize', - this.scrollListener, - this.props.useCapture, - ); - }, - }, - { - key: 'getParentElement', - value: function getParentElement(el) { - var scrollParent = - this.props.getScrollParent && this.props.getScrollParent(); - if (scrollParent != null) { - return scrollParent; - } - return el && el.parentNode; - }, - }, - { - key: 'filterProps', - value: function filterProps(props) { - return props; - }, - }, - { - key: 'attachScrollListener', - value: function attachScrollListener() { - var parentElement = this.getParentElement(this.scrollComponent); - - if (!this.props.hasMore || !parentElement) { - return; - } - - var scrollEl = window; - if (this.props.useWindow === false) { - scrollEl = parentElement; - } - - scrollEl.addEventListener( - 'mousewheel', - this.mousewheelListener, - this.props.useCapture, - ); - scrollEl.addEventListener( - 'scroll', - this.scrollListener, - this.props.useCapture, - ); - scrollEl.addEventListener( - 'resize', - this.scrollListener, - this.props.useCapture, - ); - - if (this.props.initialLoad) { - this.scrollListener(); - } - }, - }, - { - key: 'mousewheelListener', - value: function mousewheelListener(e) { - // Prevents Chrome hangups - // See: https://stackoverflow.com/questions/47524205/random-high-content-download-time-in-chrome/47684257#47684257 - if (e.deltaY === 1) { - e.preventDefault(); - } - }, - }, - { - key: 'scrollListener', - value: function scrollListener() { - var el = this.scrollComponent; - var scrollEl = window; - var parentNode = this.getParentElement(el); - - var offset = void 0; - if (this.props.useWindow) { - var doc = - document.documentElement || - document.body.parentNode || - document.body; - var scrollTop = - scrollEl.pageYOffset !== undefined - ? scrollEl.pageYOffset - : doc.scrollTop; - if (this.props.isReverse) { - offset = scrollTop; - } else { - offset = this.calculateOffset(el, scrollTop); - } - } else if (this.props.isReverse) { - offset = parentNode.scrollTop; - } else { - offset = - el.scrollHeight - parentNode.scrollTop - parentNode.clientHeight; - } - - // Here we make sure the element is visible as well as checking the offset - if ( - offset < Number(this.props.threshold) && - el && - el.offsetParent !== null - ) { - this.detachScrollListener(); - // Call loadMore after detachScrollListener to allow for non-async loadMore functions - if (typeof this.props.loadMore === 'function') { - this.props.loadMore((this.pageLoaded += 1)); - } - } - }, - }, - { - key: 'calculateOffset', - value: function calculateOffset(el, scrollTop) { - if (!el) { - return 0; - } - - return ( - this.calculateTopPosition(el) + - (el.offsetHeight - scrollTop - window.innerHeight) - ); - }, - }, - { - key: 'calculateTopPosition', - value: function calculateTopPosition(el) { - if (!el) { - return 0; - } - return el.offsetTop + this.calculateTopPosition(el.offsetParent); - }, - }, - { - key: 'render', - value: function render() { - var _this2 = this; - - var renderProps = this.filterProps(this.props); - - var children = renderProps.children, - element = renderProps.element, - hasMore = renderProps.hasMore, - initialLoad = renderProps.initialLoad, - isReverse = renderProps.isReverse, - loader = renderProps.loader, - loadMore = renderProps.loadMore, - pageStart = renderProps.pageStart, - ref = renderProps.ref, - threshold = renderProps.threshold, - useCapture = renderProps.useCapture, - useWindow = renderProps.useWindow, - getScrollParent = renderProps.getScrollParent, - props = _objectWithoutProperties(renderProps, [ - 'children', - 'element', - 'hasMore', - 'initialLoad', - 'isReverse', - 'loader', - 'loadMore', - 'pageStart', - 'ref', - 'threshold', - 'useCapture', - 'useWindow', - 'getScrollParent', - ]); - - props.ref = function(node) { - _this2.scrollComponent = node; - if (ref) { - ref(node); - } - }; - - var childrenArray = [children]; - if (hasMore) { - if (loader) { - isReverse - ? childrenArray.unshift(loader) - : childrenArray.push(loader); - } else if (this.defaultLoader) { - isReverse - ? childrenArray.unshift(this.defaultLoader) - : childrenArray.push(this.defaultLoader); - } - } - return _react2.default.createElement(element, props, childrenArray); - }, - }, - ]); - - return InfiniteScroll; -})(_react.Component); - -InfiniteScroll.propTypes = { - children: _propTypes2.default.node.isRequired, - element: _propTypes2.default.node, - hasMore: _propTypes2.default.bool, - initialLoad: _propTypes2.default.bool, - isReverse: _propTypes2.default.bool, - loader: _propTypes2.default.node, - loadMore: _propTypes2.default.func.isRequired, - pageStart: _propTypes2.default.number, - ref: _propTypes2.default.func, - getScrollParent: _propTypes2.default.func, - threshold: _propTypes2.default.number, - useCapture: _propTypes2.default.bool, - useWindow: _propTypes2.default.bool, -}; -InfiniteScroll.defaultProps = { - element: 'div', - hasMore: false, - initialLoad: true, - pageStart: 0, - ref: null, - threshold: 250, - useWindow: true, - isReverse: false, - useCapture: false, - loader: null, - getScrollParent: null, -}; -exports.default = InfiniteScroll; -module.exports = exports['default']; diff --git a/src/InfiniteScroll.js b/src/InfiniteScroll.js index 2696d46..06a988b 100644 --- a/src/InfiniteScroll.js +++ b/src/InfiniteScroll.js @@ -174,7 +174,7 @@ export default class InfiniteScroll extends Component { this.detachScrollListener(); // Call loadMore after detachScrollListener to allow for non-async loadMore functions if (typeof this.props.loadMore === 'function') { - this.props.loadMore((this.pageLoaded += 1)); + this.props.hasMore && this.props.loadMore((this.pageLoaded += 1)); } } } diff --git a/yarn.lock b/yarn.lock index 99a7807..943f5d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -202,6 +202,14 @@ array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" +array.prototype.flat@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#812db8f02cad24d3fab65dd67eabe3b8903494a4" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.10.0" + function-bind "^1.1.1" + arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -299,7 +307,7 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@^6.24.1, babel-core@^6.26.0: +babel-core@^6.26.0, babel-core@^6.26.3: version "6.26.3" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" dependencies: @@ -518,9 +526,9 @@ babel-plugin-check-es2015-constants@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-istanbul@^4.1.1: +babel-plugin-istanbul@^4.1.6: version "4.1.6" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45" + resolved "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45" dependencies: babel-plugin-syntax-object-rest-spread "^6.13.0" find-up "^2.1.0" @@ -1765,46 +1773,50 @@ entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" -enzyme-adapter-react-16@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.1.1.tgz#a8f4278b47e082fbca14f5bfb1ee50ee650717b4" +enzyme-adapter-react-16@^1.1.1: + version "1.7.0" + resolved "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.7.0.tgz#90344395a89624edbe7f0e443bc19fef62bf1f9f" dependencies: - enzyme-adapter-utils "^1.3.0" - lodash "^4.17.4" - object.assign "^4.0.4" + enzyme-adapter-utils "^1.9.0" + function.prototype.name "^1.1.0" + object.assign "^4.1.0" object.values "^1.0.4" - prop-types "^15.6.0" - react-reconciler "^0.7.0" + prop-types "^15.6.2" + react-is "^16.6.1" react-test-renderer "^16.0.0-0" -enzyme-adapter-utils@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.3.0.tgz#d6c85756826c257a8544d362cc7a67e97ea698c7" +enzyme-adapter-utils@^1.9.0: + version "1.9.0" + resolved "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.9.0.tgz#3997c20f3387fdcd932b155b3740829ea10aa86c" dependencies: - lodash "^4.17.4" - object.assign "^4.0.4" - prop-types "^15.6.0" + function.prototype.name "^1.1.0" + object.assign "^4.1.0" + prop-types "^15.6.2" + semver "^5.6.0" -enzyme@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.3.0.tgz#0971abd167f2d4bf3f5bd508229e1c4b6dc50479" +enzyme@^3.3.0: + version "3.7.0" + resolved "https://registry.npmjs.org/enzyme/-/enzyme-3.7.0.tgz#9b499e8ca155df44fef64d9f1558961ba1385a46" dependencies: + array.prototype.flat "^1.2.1" cheerio "^1.0.0-rc.2" - function.prototype.name "^1.0.3" - has "^1.0.1" + function.prototype.name "^1.1.0" + has "^1.0.3" is-boolean-object "^1.0.0" - is-callable "^1.1.3" + is-callable "^1.1.4" is-number-object "^1.0.3" is-string "^1.0.4" is-subset "^0.1.1" - lodash "^4.17.4" - object-inspect "^1.5.0" + lodash.escape "^4.0.1" + lodash.isequal "^4.5.0" + object-inspect "^1.6.0" object-is "^1.0.1" object.assign "^4.1.0" object.entries "^1.0.4" object.values "^1.0.4" raf "^3.4.0" rst-selector-parser "^2.2.3" + string.prototype.trim "^1.1.2" errno@^0.1.3: version "0.1.7" @@ -1818,7 +1830,7 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.6.1, es-abstract@^1.7.0: +es-abstract@^1.10.0, es-abstract@^1.5.0, es-abstract@^1.6.1, es-abstract@^1.7.0: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" dependencies: @@ -2263,13 +2275,13 @@ fsevents@^1.0.0, fsevents@^1.1.2: nan "^2.9.2" node-pre-gyp "^0.10.0" -function-bind@^1.1.0, function-bind@^1.1.1: +function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" -function.prototype.name@^1.0.3: +function.prototype.name@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327" + resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327" dependencies: define-properties "^1.1.2" function-bind "^1.1.1" @@ -2471,7 +2483,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.1, has@^1.0.2: +has@^1.0.1, has@^1.0.2, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: @@ -2691,6 +2703,10 @@ is-callable@^1.1.1, is-callable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + is-ci@^1.0.10: version "1.1.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.1.0.tgz#247e4162e7860cebbdaf30b774d6b0ac7dcfe7a5" @@ -3296,6 +3312,10 @@ lodash.create@3.1.1: lodash._basecreate "^3.0.0" lodash._isiterateecall "^3.0.0" +lodash.escape@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" + lodash.flattendeep@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" @@ -3308,6 +3328,10 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + lodash.keys@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -3797,9 +3821,9 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.5.0: +object-inspect@^1.6.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" object-is@^1.0.1: version "1.0.1" @@ -3815,7 +3839,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.0.4, object.assign@^4.1.0: +object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" dependencies: @@ -4151,6 +4175,13 @@ prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1: loose-envify "^1.3.1" object-assign "^4.1.1" +prop-types@^15.6.2: + version "15.6.2" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" + dependencies: + loose-envify "^1.3.1" + object-assign "^4.1.1" + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -4264,14 +4295,9 @@ react-is@^16.4.1: version "16.4.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.4.1.tgz#d624c4650d2c65dbd52c72622bbf389435d9776e" -react-reconciler@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.7.0.tgz#9614894103e5f138deeeb5eabaf3ee80eb1d026d" - dependencies: - fbjs "^0.8.16" - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.0" +react-is@^16.6.1: + version "16.6.3" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.6.3.tgz#d2d7462fcfcbe6ec0da56ad69047e47e56e7eac0" react-test-renderer@^16.0.0, react-test-renderer@^16.0.0-0: version "16.4.1" @@ -4572,6 +4598,10 @@ sax@^1.2.1, sax@^1.2.4: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" +semver@^5.6.0: + version "5.6.0" + resolved "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -4844,6 +4874,14 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string.prototype.trim@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.0" + function-bind "^1.0.2" + string_decoder@^1.0.0, string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"