react-use-infinite-loading
Version:
Infinite scroll hook for React. Supports multiple scroll directions.
116 lines (102 loc) • 3.06 kB
JavaScript
var react = require('react');
var useInfiniteScroll = function useInfiniteScroll(_ref) {
var callback = _ref.callback,
hasMore = _ref.hasMore,
_ref$startPage = _ref.startPage,
startPage = _ref$startPage === void 0 ? 1 : _ref$startPage,
_ref$offset = _ref.offset,
offset = _ref$offset === void 0 ? 250 : _ref$offset,
direction = _ref.direction;
var ref = react.useRef(null);
var _useState = react.useState(false),
firstScroll = _useState[0],
setFirstScroll = _useState[1];
var containerRef = react.useRef(null);
var _useState2 = react.useState(false),
isLoading = _useState2[0],
setIsLoading = _useState2[1];
var _useState3 = react.useState(startPage),
page = _useState3[0],
setPage = _useState3[1];
var setRef = react.useCallback(function (node) {
if (node) {
ref.current = node;
}
}, []);
var setContainerRef = react.useCallback(function (node) {
if (node) {
containerRef.current = node;
}
}, []);
var fetchData = function fetchData(page) {
try {
setIsLoading(true);
return Promise.resolve(callback(page)).then(function () {
setIsLoading(false);
});
} catch (e) {
return Promise.reject(e);
}
};
react.useEffect(function () {
var func = function func() {
try {
return Promise.resolve(fetchData(page)).then(function () {
if (direction === 'top') containerRef.current.scrollTo(0, offset);
});
} catch (e) {
return Promise.reject(e);
}
};
func();
}, [page]);
react.useLayoutEffect(function () {
if (!hasMore) return;
var currentRef = ref.current;
var options = {
root: null,
rootMargin: direction === 'bottom' ? "0px 0px " + offset + "px 0px" : offset + "px 0px 0px 0px"
};
var loadMore = function loadMore(entries) {
try {
entries.forEach(function (_ref2) {
var isIntersecting = _ref2.isIntersecting;
if (isIntersecting && !isLoading) {
setPage(function (prev) {
return prev + 1;
});
}
});
return Promise.resolve();
} catch (e) {
return Promise.reject(e);
}
};
var observer = new IntersectionObserver(loadMore, options);
observer.observe(currentRef);
return function () {
observer.disconnect();
};
}, [ref, hasMore, isLoading]);
react.useLayoutEffect(function () {
if (direction === 'top' && !firstScroll) {
containerRef.current.scrollIntoView({
block: 'end',
inline: 'nearest'
});
}
});
react.useEffect(function () {
window.addEventListener('scroll', function () {
return setFirstScroll(true);
});
return function () {
return window.removeEventListener('scroll', function () {
return setFirstScroll(true);
});
};
}, []);
return [setRef, setContainerRef, isLoading];
};
module.exports = useInfiniteScroll;
//# sourceMappingURL=index.js.map