react-ketting
Version:
Ketting bindings for React
100 lines • 3.98 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.usePagedCollection = void 0;
const react_1 = require("react");
const use_read_resource_1 = require("./use-read-resource");
/**
* The usePagedCollection hook works similar to useCollection, but has the
* ability to load in additional pages of items.
*
* For this to work, the API needs to expose a "next" link on the collection.
* As long as there are "next" links, more pages can be loaded in.
*
* Additional items from collection pages will be appended to "items",
* allowing frontends to build 'infinite scroll' features.
*
* Example call:
*
* <pre>
* const {
* loading,
* error,
* items,
* hasNextPage,
* loadNextPage
* } = usePagedResource<Article>(resource);
* </pre>
*
* The resource may be passed as a Resource object, a Promise<Resource>, or a
* uri string.
*
* Returned properties:
*
* * loading - will be true every time we're going to the server and fetch a
* a new page.
* * error - Will be null or an error object.
* * items - Will contain an array of resources, each typed Resource<T> where
* T is the passed generic argument.
* * hasNextPage - Will be true if the server has another page.
* * loadNextPage - Loads the next page, and appends the new items to the
* items array.
*/
function usePagedCollection(resourceLike, options) {
var _a;
const rel = (options === null || options === void 0 ? void 0 : options.rel) || 'item';
const [items, setItems] = (0, react_1.useState)([]);
const [currentCollectionResource, setCurrentCollectionResource] = (0, react_1.useState)(resourceLike);
// This is the 'base collection'
const bc = (0, use_read_resource_1.useReadResource)(resourceLike, {
refreshOnStale: options === null || options === void 0 ? void 0 : options.refreshOnStale,
// This header will be included on the first, uncached fetch.
// This may be helpful to the server and instruct it to embed
// all collection members in that initial fetch.
initialGetRequestHeaders: {
Prefer: 'transclude=' + rel,
}
});
// This is the 'current collection
const cc = (0, use_read_resource_1.useReadResource)(currentCollectionResource, {
refreshOnStale: options === null || options === void 0 ? void 0 : options.refreshOnStale,
// This header will be included on the first, uncached fetch.
// This may be helpful to the server and instruct it to embed
// all collection members in that initial fetch.
initialGetRequestHeaders: {
Prefer: 'transclude=' + rel,
}
});
(0, react_1.useEffect)(() => {
// We're loading a new 'base collection', so lets clear any items we got
setItems([]);
// Set the 'current' page back to the first page in the collection.
setCurrentCollectionResource(resourceLike);
}, [bc.resource]);
(0, react_1.useEffect)(() => {
if (cc.resourceState) {
// This effect gets triggered when we get data for a new page.
// When we do, append the items to our array.
setItems([
...items,
...cc.resourceState.followAll(rel)
]);
}
}, [(_a = cc.resourceState) === null || _a === void 0 ? void 0 : _a.uri]);
const hasNextPage = !cc.loading && cc.resourceState && cc.resourceState.links.has('next');
const loadNextPage = () => {
if (!hasNextPage) {
console.warn('loadNextPage was called, but there was no next page');
return;
}
setCurrentCollectionResource(cc.resourceState.follow('next'));
};
return {
loading: cc.loading,
error: cc.error,
items,
hasNextPage,
loadNextPage,
};
}
exports.usePagedCollection = usePagedCollection;
//# sourceMappingURL=use-paged-collection.js.map
;