S
SolidJS•11mo ago
Temboard

can't reset createInfiniteScroll

hello, at our team we are trying to create infinite scrolling with filters with @solid-primitives/pagination with signal: createInfiniteScroll but we encoutered a problem: You can't reset createInfiniteScroll cleanly, while you can clear all values like this: batch(() => { setPage(0); setEnd(false); setPages([]); }); but this will result in running the fetcher with page=1 and then page=1 see video In the stackblitz example there is also copy of createInfiniteScroll for debugging Here is a minimal reproduction scenario: https://stackblitz.com/edit/solidjs-template-raszfy?file=src%2FApp.tsx Do you please know how to fix it?
OskarMihalik
StackBlitz
Solid Infinite Scroll reset Demo - StackBlitz
A Solid TypeScript project based on @solid-primitives/pagination, solid-js, solid-transition-group, typescript, vite and vite-plugin-solid
2 Replies
Rachael
Rachael•7mo ago
Did you ever get this figured out? I think we are struggling with something similar...
Temboard
Temboard•7mo ago
i needed to change createComputed and add refetch, see the changed cade:
export function createInfiniteScroll<T extends Data<E>, E>(
fetcher: (page: number) => Promise<T>
): [
pages: Accessor<E[]>,
loader: Directive,
options: {
page: Accessor<number>
setPage: Setter<number>
setPages: Setter<E[]>
end: Accessor<boolean>
setEnd: Setter<boolean>
refetch: (info?: unknown) => T | Promise<T | undefined> | null | undefined
newestData: Resource<T>
}
] {
const [pages, setPages] = createSignal<E[]>([])
const [page, setPage] = createSignal(0)
const [end, setEnd] = createSignal(false)

const [contents, { refetch }] = createResource(page, fetcher)

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) => {
return p + 1
})
}
})
onCleanup(() => io.disconnect())
add = (el: Element) => {
io.observe(el)
tryOnCleanup(() => io.unobserve(el))
}
}

createComputed(() => {
const content = contents()
if (!content) return
batch(() => {
if (content.results.length === 0) setEnd(true)
else {
setEnd(false)
}
setPages((p) => [...p, ...content.results])
})
})

return [
pages,
add,
{
page,
setPage,
setPages,
end,
setEnd,
refetch,
newestData: contents,
},
]
}
export function createInfiniteScroll<T extends Data<E>, E>(
fetcher: (page: number) => Promise<T>
): [
pages: Accessor<E[]>,
loader: Directive,
options: {
page: Accessor<number>
setPage: Setter<number>
setPages: Setter<E[]>
end: Accessor<boolean>
setEnd: Setter<boolean>
refetch: (info?: unknown) => T | Promise<T | undefined> | null | undefined
newestData: Resource<T>
}
] {
const [pages, setPages] = createSignal<E[]>([])
const [page, setPage] = createSignal(0)
const [end, setEnd] = createSignal(false)

const [contents, { refetch }] = createResource(page, fetcher)

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) => {
return p + 1
})
}
})
onCleanup(() => io.disconnect())
add = (el: Element) => {
io.observe(el)
tryOnCleanup(() => io.unobserve(el))
}
}

createComputed(() => {
const content = contents()
if (!content) return
batch(() => {
if (content.results.length === 0) setEnd(true)
else {
setEnd(false)
}
setPages((p) => [...p, ...content.results])
})
})

return [
pages,
add,
{
page,
setPage,
setPages,
end,
setEnd,
refetch,
newestData: contents,
},
]
}
to reset infinite scroll call: () =>{ batch(() => { setPage(0) setEnd(false) setPages([]) }) // eslint-disable-next-line no-void void refetch() } This should work but it was long time ago so I don't remember details. In the end we moved to normal pagination 😄