-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: Move infinite query logic into queryCache
- Loading branch information
1 parent
5a5ad74
commit 7cd1af1
Showing
6 changed files
with
155 additions
and
156 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,16 @@ | ||
import React from 'react' | ||
|
||
// | ||
|
||
import { useBaseQuery } from './useBaseQuery' | ||
import { useQueryArgs, useGetLatest, handleSuspense } from './utils' | ||
import { useQueryArgs, handleSuspense } from './utils' | ||
|
||
export function useInfiniteQuery(...args) { | ||
const queryInfoRef = React.useRef() | ||
let [queryKey, config] = useQueryArgs(args) | ||
|
||
const { getFetchMore } = config | ||
const getGetFetchMore = useGetLatest(getFetchMore) | ||
|
||
// The default queryFn will query all pages and map them together | ||
const originalQueryFn = config.queryFn | ||
|
||
config.queryFn = async () => { | ||
const data = [] | ||
const pageVariables = [...queryInfoRef.current.query.pageVariables] | ||
const rebuiltPageVariables = [] | ||
|
||
do { | ||
const args = pageVariables.shift() | ||
|
||
if (!data.length) { | ||
// the first page query doesn't need to be rebuilt | ||
data.push(await originalQueryFn(...args)) | ||
rebuiltPageVariables.push(args) | ||
} else { | ||
// get an up-to-date cursor based on the previous data set | ||
const nextCursor = getGetFetchMore()(data[data.length - 1], data) | ||
|
||
// break early if there's no next cursor | ||
// otherwise we'll start from the beginning | ||
// which will cause unwanted duplication | ||
if (!nextCursor) { | ||
break | ||
} | ||
|
||
const pageArgs = [ | ||
// remove the last argument (the previously saved cursor) | ||
...args.slice(0, -1), | ||
nextCursor, | ||
] | ||
|
||
data.push(await originalQueryFn(...pageArgs)) | ||
rebuiltPageVariables.push(pageArgs) | ||
} | ||
} while (pageVariables.length) | ||
|
||
queryInfoRef.current.query.canFetchMore = getGetFetchMore()( | ||
data[data.length - 1], | ||
data | ||
) | ||
queryInfoRef.current.query.pageVariables = rebuiltPageVariables | ||
|
||
return data | ||
} | ||
config.infinite = true | ||
|
||
const queryInfo = useBaseQuery(queryKey, config) | ||
|
||
if ( | ||
typeof queryInfo.query.canFetchMore === 'undefined' && | ||
typeof queryInfo.data !== 'undefined' | ||
) { | ||
queryInfo.query.canFetchMore = getGetFetchMore()( | ||
queryInfo.data[queryInfo.data.length - 1], | ||
queryInfo.data | ||
) | ||
} | ||
|
||
queryInfoRef.current = queryInfo | ||
|
||
let { | ||
data = [], | ||
query: { canFetchMore }, | ||
} = queryInfo | ||
|
||
// Here we seed the pageVariabes for the query | ||
if (!queryInfo.query.pageVariables) { | ||
queryInfo.query.pageVariables = [[...queryInfo.query.queryKey]] | ||
} | ||
|
||
const fetchMore = React.useCallback( | ||
( | ||
fetchMoreInfo = queryInfoRef.current.query.canFetchMore, | ||
{ previous = false } = {} | ||
) => | ||
queryInfoRef.current.query.canFetchMore | ||
? queryInfoRef.current.query.fetch({ | ||
queryFn: async (...args) => { | ||
try { | ||
queryInfoRef.current.query.setState(old => ({ | ||
...old, | ||
isFetchingMore: previous ? 'previous' : 'next', | ||
})) | ||
|
||
const newArgs = previous | ||
? [fetchMoreInfo, ...args] | ||
: [...args, fetchMoreInfo] | ||
queryInfoRef.current.query.pageVariables[ | ||
previous ? 'unshift' : 'push' | ||
](newArgs) | ||
|
||
const newData = await originalQueryFn(...newArgs) | ||
|
||
const data = previous | ||
? [newData, ...queryInfoRef.current.data] | ||
: [...queryInfoRef.current.data, newData] | ||
|
||
queryInfoRef.current.query.canFetchMore = getGetFetchMore()( | ||
newData, | ||
data | ||
) | ||
|
||
return data | ||
} finally { | ||
queryInfoRef.current.query.setState(old => ({ | ||
...old, | ||
isFetchingMore: false, | ||
})) | ||
} | ||
}, | ||
}) | ||
: void 0, | ||
[getGetFetchMore, originalQueryFn] | ||
) | ||
|
||
handleSuspense(queryInfo) | ||
|
||
return { | ||
...queryInfo, | ||
data, | ||
canFetchMore, | ||
fetchMore, | ||
} | ||
return queryInfo | ||
} |
Oops, something went wrong.