Skip to content

Commit

Permalink
Pass pageSWRs to swrDataToOffset (#52)
Browse files Browse the repository at this point in the history
* pass pageSWRs to swrDataToOffset

* fix format and type checker

* tiny performance improvement

* fix tsconfig
  • Loading branch information
shuding authored and pacocoursey committed Nov 6, 2019
1 parent d9b9d99 commit 80c4b3f
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 25 deletions.
17 changes: 12 additions & 5 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,22 @@ export type revalidateType = (
revalidateOpts: RevalidateOptionInterface
) => Promise<boolean>

export type pagesWithSWRType = () => void
export type pagesPropsInterface<Offset> = {
export type pagesWithSWRType<Data, Error> = (
swr: responseInterface<Data, Error>
) => responseInterface<Data, Error>
export type pagesPropsInterface<Offset, Data, Error> = {
// offset can be any type
offset: Offset
withSWR: pagesWithSWRType
withSWR: pagesWithSWRType<Data, Error>
}

export type pageComponentType = (props: pagesPropsInterface<any>) => any
export type pageOffsetMapperType<Offset> = (data: any) => Offset
export type pageComponentType<Offset, Data, Error> = (
props: pagesPropsInterface<Offset, Data, Error>
) => any
export type pageOffsetMapperType<Offset, Data, Error> = (
data: any,
pageSWRs: responseInterface<Data, Error>[]
) => Offset

export type pagesResponseInterface = {
pages: any
Expand Down
44 changes: 24 additions & 20 deletions src/use-swr-pages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ function App () {
}
*/

export function useSWRPages<OffsetType>(
export function useSWRPages<OffsetType, Data, Error>(
pageKey: string,
pageFn: pageComponentType,
swrDataToOffset: pageOffsetMapperType<OffsetType>,
pageFn: pageComponentType<OffsetType, Data, Error>,
swrDataToOffset: pageOffsetMapperType<OffsetType, Data, Error>,
deps: any[] = []
): pagesResponseInterface {
const pageCountKey = `_swr_page_count_` + pageKey
Expand All @@ -103,7 +103,7 @@ export function useSWRPages<OffsetType>(
const [pageOffsets, setPageOffsets] = useState<OffsetType[]>(
cacheGet(pageOffsetKey) || [null]
)
const [pageSWRs, setPageSWRs] = useState<responseInterface<any, any>[]>([])
const [pageSWRs, setPageSWRs] = useState<responseInterface<Data, Error>[]>([])

const pageCacheRef = useRef([])
const pageFnRef = useRef(pageFn)
Expand Down Expand Up @@ -137,6 +137,8 @@ export function useSWRPages<OffsetType>(
return c + 1
})
}, [isLoadingMore || isReachingEnd])
const _pageFn = useCallback(pageFn, deps)
pageFnRef.current = _pageFn

const pages = useMemo(() => {
const getWithSWR = id => swr => {
Expand All @@ -149,20 +151,22 @@ export function useSWRPages<OffsetType>(
setPageSWRs(swrs => {
const _swrs = [...swrs]
_swrs[id] = swr

if (typeof swr.data !== 'undefined') {
// set next page's offset
const newPageOffset = swrDataToOffset(swr.data, _swrs)
if (pageOffsets[id + 1] !== newPageOffset) {
setPageOffsets(arr => {
const _arr = [...arr]
_arr[id + 1] = newPageOffset
cacheSet(pageOffsetKey, _arr)
return _arr
})
}
}

return _swrs
})
if (swr.data) {
// set next page's offset
const newPageOffset = swrDataToOffset(swr.data)
if (pageOffsets[id + 1] !== newPageOffset) {
setPageOffsets(arr => {
const _arr = [...arr]
_arr[id + 1] = newPageOffset
cacheSet(pageOffsetKey, _arr)
return _arr
})
}
}
}
return swr
}
Expand All @@ -174,26 +178,26 @@ export function useSWRPages<OffsetType>(
if (
!pageCache[i] ||
pageCache[i].offset !== pageOffsets[i] ||
pageCache[i].pageFn !== pageFn
pageCache[i].pageFn !== _pageFn
) {
// when props change or at init
// render the page and cache it
pageCache[i] = {
component: (
<Page
key={`page-${pageOffsets[i]}`}
key={`page-${pageOffsets[i]}-${i}`}
offset={pageOffsets[i]}
withSWR={getWithSWR(i)}
/>
),
pageFn,
pageFn: _pageFn,
offset: pageOffsets[i]
}
}
p.push(pageCache[i].component)
}
return p
}, [pageFn, pageCount, pageSWRs, pageOffsets, ...deps])
}, [_pageFn, pageCount, pageSWRs, pageOffsets, pageKey])

return {
pages,
Expand Down
54 changes: 54 additions & 0 deletions test/use-swr-pages.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { useEffect } from 'react'
import { cleanup, render, waitForDomChange } from '@testing-library/react'

import useSWR, { useSWRPages } from '../src'

describe('useSWRPages', () => {
afterEach(cleanup)

it('should render the first page componet', async () => {
function Page() {
const { pages } = useSWRPages<number, string, any>(
'page-1',
({ offset }) => {
return 'page ' + (offset || 0)
},
() => 0
)

return pages
}
const { container } = render(<Page />)
expect(container.textContent).toMatchInlineSnapshot(`"page 0"`)
})

it('should render the multiple pages', async () => {
function Page() {
const { pages, pageCount, isLoadingMore, loadMore } = useSWRPages<
number,
string,
any
>(
'page-2',
({ offset, withSWR }) => {
const { data } = withSWR(useSWR(String(offset || 0), v => v))
return 'page ' + data + ', '
},
(_, pageSWRs) => pageSWRs.length
)

useEffect(() => {
// load next page if the current one is ready
if (pageCount <= 2 && !isLoadingMore) loadMore()
}, [pageCount, isLoadingMore])

return pages
}
const { container } = render(<Page />)
await waitForDomChange({ container }) // mount
// should have 3 pages
expect(container.textContent).toMatchInlineSnapshot(
`"page 0, page 1, page 2, "`
)
})
})

0 comments on commit 80c4b3f

Please sign in to comment.