Skip to content
Open
105 changes: 58 additions & 47 deletions packages/pagination/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,64 +253,75 @@ export type _E = JSX.Element;
* ```
* @param fetcher `(page: number) => Promise<T[]>`
* @return `pages()` is an accessor contains array of contents
* @property `pages.loading` is a boolean indicator for the loading state
* @property `pages.error` contains any error encountered
* @return `infiniteScrollLoader` is a directive used to set the loader element
* @method `page` is an accessor that contains page number
* @method `setPage` allows to manually change the page number
* @method `setPages` allows to manually change the contents of the page
* @method `end` is a boolean indicator for end of the page
* @method `error` contains any error encountered
* @method `setEnd` allows to manually change the end
*/
export function createInfiniteScroll<T>(fetcher: (page: number) => Promise<T[]>): [
pages: Accessor<T[]>,
loader: (el: Element) => void,
options: {
page: Accessor<number>;
setPage: Setter<number>;
setPages: Setter<T[]>;
end: Accessor<boolean>;
setEnd: Setter<boolean>;
},
pages: Accessor<T[]>,
loader: (el: Element) => void,
options: {
page: Accessor<number>
setPage: Setter<number>
setPages: Setter<T[]>
end: Accessor<boolean>
setEnd: Setter<boolean>
error: Accessor<any>
}
] {
const [pages, setPages] = createSignal<T[]>([]);
const [page, setPage] = createSignal(0);
const [end, setEnd] = createSignal(false);
const [pages, setPages] = createSignal<T[]>([])
const [page, setPage] = createSignal(0)
const [end, setEnd] = createSignal(false)
const [error, setError] = createSignal<any>(null)

let add: (el: Element) => void = noop;
if (!isServer) {
const io = new IntersectionObserver(e => {
if (e.length > 0 && e[0]!.isIntersecting && !end() && !contents.loading) {
setPage(p => p + 1);
}
});
onCleanup(() => io.disconnect());
add = (el: Element) => {
io.observe(el);
tryOnCleanup(() => io.unobserve(el));
};
}
const [contents] = createResource(page, async (p) => {
setError(null)
try {
const result = await fetcher(p)
return result
} catch (e) {
setError(e)
return []
}
})

const [contents] = createResource(page, fetcher);
createComputed(() => {
const content = contents()
Comment thread
007qr marked this conversation as resolved.
Outdated
if (!content) return
batch(() => {
if (content.length === 0) setEnd(true)
setPages((prev) => [...prev, ...content])
})
})

createComputed(() => {
const content = contents.latest;
if (!content) return;
batch(() => {
if (content.length === 0) setEnd(true);
setPages(p => [...p, ...content]);
});
});
let add: (el: Element) => void = () => {}
if (!isServer) {
const io = new IntersectionObserver((entries) => {
if (entries[0]?.isIntersecting && !end()) {
setPage((p) => p + 1)
}
})
onCleanup(() => io.disconnect())
add = (el: Element) => {
io.observe(el)
tryOnCleanup(() => io.unobserve(el))
}
}

return [
pages,
add,
{
page: page,
setPage: setPage,
setPages: setPages,
end: end,
setEnd: setEnd,
},
];
return [
pages,
add,
{
page,
setPage,
setPages,
end,
setEnd,
error,
},
]
}
Loading