-
Notifications
You must be signed in to change notification settings - Fork 0
[WIP] New useQueryState Hook #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
c4a8a12
b8d6851
4f00031
ff658ee
bea1eb5
a164794
f9017e6
7bf9b4e
05e18d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,13 @@ | ||
'use client' | ||
import * as React from 'react' | ||
import { notifyManager } from '@tanstack/query-core' | ||
|
||
import { useQueryClient } from './QueryClientProvider' | ||
import { useQueryState } from './useQueryState' | ||
import type { QueryClient, QueryFilters } from '@tanstack/query-core' | ||
|
||
export function useIsFetching( | ||
filters?: QueryFilters, | ||
queryClient?: QueryClient, | ||
): number { | ||
const client = useQueryClient(queryClient) | ||
const queryCache = client.getQueryCache() | ||
|
||
return React.useSyncExternalStore( | ||
React.useCallback( | ||
(onStoreChange) => | ||
queryCache.subscribe(notifyManager.batchCalls(onStoreChange)), | ||
[queryCache], | ||
), | ||
() => client.isFetching(filters), | ||
() => client.isFetching(filters), | ||
) | ||
return useQueryState( | ||
{ filters: { ...filters, fetchStatus: 'fetching' } }, | ||
queryClient, | ||
).length | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,67 @@ | ||||||||||||
'use client' | ||||||||||||
import * as React from 'react' | ||||||||||||
|
||||||||||||
import { notifyManager, replaceEqualDeep } from '@tanstack/query-core' | ||||||||||||
import { useQueryClient } from './QueryClientProvider' | ||||||||||||
import type { | ||||||||||||
DefaultError, | ||||||||||||
Query, | ||||||||||||
QueryCache, | ||||||||||||
QueryClient, | ||||||||||||
QueryFilters, | ||||||||||||
QueryKey, | ||||||||||||
QueryState, | ||||||||||||
} from '@tanstack/query-core' | ||||||||||||
|
||||||||||||
type QueryStateOptions<TResult = QueryState> = { | ||||||||||||
filters?: QueryFilters | ||||||||||||
select?: (query: Query<unknown, DefaultError, unknown, QueryKey>) => TResult | ||||||||||||
} | ||||||||||||
|
||||||||||||
function getResult<TResult = QueryState>( | ||||||||||||
queryCache: QueryCache, | ||||||||||||
options: QueryStateOptions<TResult>, | ||||||||||||
): Array<TResult> { | ||||||||||||
return queryCache | ||||||||||||
.findAll(options.filters) | ||||||||||||
.map( | ||||||||||||
(query): TResult => | ||||||||||||
(options.select ? options.select(query) : query.state) as TResult, | ||||||||||||
) | ||||||||||||
} | ||||||||||||
|
||||||||||||
export function useQueryState<TResult = QueryState>( | ||||||||||||
options: QueryStateOptions<TResult> = {}, | ||||||||||||
queryClient?: QueryClient, | ||||||||||||
): Array<TResult> { | ||||||||||||
const queryCache = useQueryClient(queryClient).getQueryCache() | ||||||||||||
const optionsRef = React.useRef(options) | ||||||||||||
const result = React.useRef<Array<TResult>>() | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix TypeScript error: Initial value missing for useRef The TypeScript error indicates that Apply this fix: - const result = React.useRef<Array<TResult>>()
+ const result = React.useRef<Array<TResult>>([]) 📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Actions: pr[error] 39-39: TypeScript error TS2554: Expected 1 arguments, but got 0. |
||||||||||||
if (!result.current) { | ||||||||||||
result.current = getResult(queryCache, options) | ||||||||||||
} | ||||||||||||
Comment on lines
+40
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Revisit initialization logic Since you're initializing the Consider either:
- if (!result.current) {
- result.current = getResult(queryCache, options)
- }
+ // Initialize with current results when ref is empty
+ result.current = result.current || getResult(queryCache, options) 📝 Committable suggestion
Suggested change
|
||||||||||||
|
||||||||||||
React.useEffect(() => { | ||||||||||||
optionsRef.current = options | ||||||||||||
}) | ||||||||||||
|
||||||||||||
return React.useSyncExternalStore( | ||||||||||||
React.useCallback( | ||||||||||||
(onStoreChange) => | ||||||||||||
queryCache.subscribe(notifyManager.batchCalls(onStoreChange)), | ||||||||||||
[queryCache], | ||||||||||||
), | ||||||||||||
() => { | ||||||||||||
const nextResult = replaceEqualDeep( | ||||||||||||
result.current, | ||||||||||||
getResult(queryCache, optionsRef.current), | ||||||||||||
) | ||||||||||||
if (result.current !== nextResult) { | ||||||||||||
result.current = nextResult | ||||||||||||
} | ||||||||||||
|
||||||||||||
return result.current | ||||||||||||
}, | ||||||||||||
() => result.current, | ||||||||||||
)! | ||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add JSDoc documentation for useQueryState
This is a new public API, and it should have descriptive documentation to help users understand its purpose and usage.
Add JSDoc documentation:
📝 Committable suggestion