Skip to content
Open
Changes from 3 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
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()
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