Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 28aad5f

Browse files
committedMar 20, 2025·
feat: all good
1 parent dc1caa1 commit 28aad5f

File tree

5 files changed

+96
-53
lines changed

5 files changed

+96
-53
lines changed
 

‎packages/use-dataloader/src/DataLoaderProvider.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
KEY_IS_NOT_STRING_ERROR,
66
} from './constants'
77
import DataLoader from './dataloader'
8+
import { marshalQueryKey } from './helpers'
89
import type { OnErrorFn, PromiseType } from './types'
910

1011
type CachedData = Record<string, unknown>
@@ -39,6 +40,7 @@ export type IDataLoaderContext = {
3940
key: string,
4041
args: UseDataLoaderInitializerArgs<ResultType>,
4142
) => DataLoader<ResultType, ErrorType>
43+
computeKey: (key: string) => string
4244
cacheKeyPrefix?: string
4345
onError?: (error: Error) => void | Promise<void>
4446
clearAllCachedData: () => void
@@ -65,14 +67,14 @@ type DataLoaderProviderProps = {
6567

6668
const DataLoaderProvider = ({
6769
children,
68-
cacheKeyPrefix = '',
70+
cacheKeyPrefix,
6971
onError,
7072
maxConcurrentRequests = DEFAULT_MAX_CONCURRENT_REQUESTS,
7173
}: DataLoaderProviderProps): ReactElement => {
7274
const requestsRef = useRef<Requests>({})
7375

7476
const computeKey = useCallback(
75-
(key: string) => `${cacheKeyPrefix ? `${cacheKeyPrefix}-` : ''}${key}`,
77+
(key: string) => marshalQueryKey([cacheKeyPrefix, key]),
7678
[cacheKeyPrefix],
7779
)
7880

@@ -201,6 +203,7 @@ const DataLoaderProvider = ({
201203
reload,
202204
reloadAll,
203205
reloadGroup,
206+
computeKey,
204207
}),
205208
[
206209
addRequest,
@@ -215,6 +218,7 @@ const DataLoaderProvider = ({
215218
reload,
216219
reloadAll,
217220
reloadGroup,
221+
computeKey,
218222
],
219223
)
220224

‎packages/use-dataloader/src/__tests__/useInfiniteDataLoader.test.tsx

+35-8
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ const config: UseInfiniteDataLoaderConfig<
1212
'page'
1313
> = {
1414
getNextPage: result => result.nextPage,
15-
pageKey: 'page',
16-
params: {
17-
page: 1,
18-
},
1915
enabled: true,
2016
}
2117

@@ -41,6 +37,9 @@ const getPrerequisite = (key: string) => {
4137

4238
return {
4339
initialProps: {
40+
baseParams: {
41+
page: 1,
42+
},
4443
config: {
4544
enabled: true,
4645
},
@@ -65,7 +64,14 @@ describe('useInfinitDataLoader', () => {
6564
it('should get the first page on mount while enabled', async () => {
6665
const { setCanResolve, initialProps } = getPrerequisite('test1')
6766
const { result } = renderHook(
68-
props => useInfiniteDataLoader(props.key, props.method, config),
67+
props =>
68+
useInfiniteDataLoader(
69+
props.key,
70+
props.method,
71+
props.baseParams,
72+
'page',
73+
config,
74+
),
6975
{
7076
initialProps,
7177
wrapper,
@@ -86,7 +92,14 @@ describe('useInfinitDataLoader', () => {
8692
it('should get the first and loadMore one page on mount while enabled', async () => {
8793
const { setCanResolve, initialProps } = getPrerequisite('test2')
8894
const { result } = renderHook(
89-
props => useInfiniteDataLoader(props.key, props.method, config),
95+
props =>
96+
useInfiniteDataLoader(
97+
props.key,
98+
props.method,
99+
props.baseParams,
100+
'page',
101+
config,
102+
),
90103
{
91104
initialProps,
92105
wrapper,
@@ -129,7 +142,14 @@ describe('useInfinitDataLoader', () => {
129142
const { setCanResolve, initialProps, resetCounter } =
130143
getPrerequisite('test3')
131144
const { result } = renderHook(
132-
props => useInfiniteDataLoader(props.key, props.method, config),
145+
props =>
146+
useInfiniteDataLoader(
147+
props.key,
148+
props.method,
149+
props.baseParams,
150+
'page',
151+
config,
152+
),
133153
{
134154
initialProps,
135155
wrapper,
@@ -191,7 +211,14 @@ describe('useInfinitDataLoader', () => {
191211
},
192212
}
193213
const { result, rerender } = renderHook(
194-
props => useInfiniteDataLoader(props.key, props.method, props.config),
214+
props =>
215+
useInfiniteDataLoader(
216+
props.key,
217+
props.method,
218+
props.baseParams,
219+
'page',
220+
props.config,
221+
),
195222
{
196223
initialProps: localInitialProps,
197224
wrapper,

‎packages/use-dataloader/src/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ export {
33
useDataLoaderContext,
44
} from './DataLoaderProvider'
55
export { useDataLoader } from './useDataLoader'
6-
export type { UseDataLoaderConfig } from './types'
6+
export type { UseDataLoaderConfig, UseInfiniteDataLoaderConfig } from './types'
77
export { DATALIFE_TIME, POLLING_INTERVAL } from './constants'
8+
export { useInfiniteDataLoader } from './useInfiniteDataLoader'

‎packages/use-dataloader/src/types.ts

+5-10
Original file line numberDiff line numberDiff line change
@@ -97,21 +97,16 @@ export type UseDataLoaderResult<ResultType, ErrorType> = {
9797
export type UseInfiniteDataLoaderConfig<
9898
ResultType,
9999
ErrorType extends Error,
100-
ParamsType,
100+
ParamsType extends Record<string, unknown>,
101101
ParamsKey extends keyof ParamsType,
102102
> = Omit<UseDataLoaderConfig<ResultType, ErrorType>, 'initialData'> & {
103-
/**
104-
* Params will be forwarded to method
105-
*/
106-
params: ParamsType
107-
/**
108-
* The key to change in params
109-
*/
110-
pageKey: ParamsKey
111103
/**
112104
* If return undefined it consider that there are no remaining page to load
113105
*/
114-
getNextPage: (result: ResultType) => ParamsType[ParamsKey]
106+
getNextPage: (
107+
lastRes: ResultType,
108+
lastParams: ParamsType,
109+
) => ParamsType[ParamsKey]
115110
/**
116111
* The initial data if no one is present in the cache before the request
117112
*/

‎packages/use-dataloader/src/useInfiniteDataLoader.ts

+48-32
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,49 @@ import type {
1616
export const useInfiniteDataLoader = <
1717
ResultType = unknown,
1818
ErrorType extends Error = Error,
19-
ParamsType = unknown,
19+
ParamsType extends Record<string, unknown> = Record<string, unknown>,
2020
ParamsPageKey extends keyof ParamsType = keyof ParamsType,
2121
>(
2222
baseKey: KeyType,
23-
method: (params?: ParamsType) => PromiseType<ResultType>,
23+
method: (params: ParamsType) => PromiseType<ResultType>,
24+
baseParams: ParamsType,
25+
pageParamKey: ParamsPageKey,
2426
config?: UseInfiniteDataLoaderConfig<
2527
ResultType,
2628
ErrorType,
2729
ParamsType,
2830
ParamsPageKey
2931
>,
3032
): UseInfiniteDataLoaderResult<ResultType, ErrorType> => {
31-
const { getOrAddRequest, onError: onGlobalError } = useDataLoaderContext()
33+
const {
34+
getOrAddRequest,
35+
computeKey,
36+
onError: onGlobalError,
37+
} = useDataLoaderContext()
3238
const {
3339
enabled = true,
3440
onError,
3541
onSuccess,
3642
keepPreviousData = false,
3743
initialData,
3844
dataLifetime,
39-
pageKey,
40-
params,
4145
getNextPage,
4246
} = config ?? {}
4347
const requestRefs = useRef<DataLoader<ResultType, ErrorType>[]>([])
44-
const [page, setPage] = useState(
45-
params && pageKey ? params[pageKey] : undefined,
46-
)
48+
const [page, setPage] = useState(baseParams[pageParamKey])
4749
const nextPageRef = useRef(page)
4850
const getNextPageRef = useRef(getNextPage)
4951
const methodRef = useRef(() =>
5052
method(
51-
pageKey && page ? ({ ...params, [pageKey]: page } as ParamsType) : params,
53+
pageParamKey && page
54+
? ({ ...baseParams, [pageParamKey]: page } as ParamsType)
55+
: baseParams,
5256
),
5357
)
5458
const paramsRef = useRef(
55-
pageKey && page ? ({ ...params, [pageKey]: page } as ParamsType) : params,
59+
pageParamKey && page
60+
? ({ ...baseParams, [pageParamKey]: page } as ParamsType)
61+
: baseParams,
5662
)
5763
const onSuccessRef = useRef(onSuccess)
5864
const onErrorRef = useRef(onError ?? onGlobalError)
@@ -62,30 +68,36 @@ export const useInfiniteDataLoader = <
6268
setCounter(current => current + 1)
6369
}, [])
6470

65-
const baseQueryKey = useMemo(
66-
() => marshalQueryKey([marshalQueryKey(baseKey), page as string | number]),
67-
[baseKey, page],
68-
)
69-
70-
useEffect(() => {
71-
requestRefs.current.forEach(request => request.removeObserver(() => null))
72-
requestRefs.current = []
73-
forceRerender()
74-
}, [baseKey, forceRerender])
71+
const baseQueryKey = useMemo(() => marshalQueryKey(baseKey), [baseKey])
7572

7673
useEffect(
7774
() => () => {
78-
requestRefs.current.forEach(request => request.removeObserver(() => null))
75+
requestRefs.current.forEach(request =>
76+
request.removeObserver(forceRerender),
77+
)
7978
},
80-
[],
79+
[forceRerender],
8180
)
8281

83-
const getCurrentRequest = useCallback(() => {
84-
const requestInRef = requestRefs.current.find(
85-
request => request.key === baseQueryKey,
82+
const getCurrentRequest = () => {
83+
const currentQueryKey = marshalQueryKey([
84+
baseQueryKey,
85+
'infinite',
86+
page as string | number,
87+
])
88+
requestRefs.current.forEach(request =>
89+
!request.key.startsWith(computeKey(baseQueryKey))
90+
? request.removeObserver(forceRerender)
91+
: undefined,
92+
)
93+
requestRefs.current = requestRefs.current.filter(({ key }) =>
94+
key.startsWith(computeKey(baseQueryKey)),
95+
)
96+
const requestInRef = requestRefs.current.find(request =>
97+
request.key.endsWith(currentQueryKey),
8698
)
8799
if (!requestInRef) {
88-
const request = getOrAddRequest<ResultType, ErrorType>(baseQueryKey, {
100+
const request = getOrAddRequest<ResultType, ErrorType>(currentQueryKey, {
89101
enabled,
90102
method: methodRef.current,
91103
})
@@ -96,7 +108,7 @@ export const useInfiniteDataLoader = <
96108
}
97109

98110
return requestInRef
99-
}, [baseQueryKey, forceRerender, enabled, getOrAddRequest])
111+
}
100112

101113
const request = getCurrentRequest()
102114

@@ -166,8 +178,10 @@ export const useInfiniteDataLoader = <
166178

167179
useEffect(() => {
168180
paramsRef.current =
169-
pageKey && page ? ({ ...params, [pageKey]: page } as ParamsType) : params
170-
}, [params, pageKey, page])
181+
pageParamKey && page
182+
? ({ ...baseParams, [pageParamKey]: page } as ParamsType)
183+
: baseParams
184+
}, [baseParams, pageParamKey, page])
171185

172186
useEffect(() => {
173187
if (needLoad) {
@@ -180,6 +194,7 @@ export const useInfiniteDataLoader = <
180194
if (getNextPageRef.current) {
181195
nextPageRef.current = getNextPageRef.current(
182196
result,
197+
paramsRef.current,
183198
) as typeof nextPageRef.current
184199
}
185200
await onSuccessLoad(result)
@@ -203,16 +218,18 @@ export const useInfiniteDataLoader = <
203218
isLoadingFirstPage,
204219
data:
205220
isLoadingFirstPage ||
206-
requestRefs.current.filter(dataloader => !!dataloader.data).length === 0
221+
[...requestRefs.current].filter(dataloader => !!dataloader.data)
222+
.length === 0
207223
? initialData
208-
: (requestRefs.current
224+
: ([...requestRefs.current]
209225
.filter(dataloader => !!dataloader.data)
210226
.map(dataloader => dataloader.data) as ResultType[]),
211227
error: request.error,
212228
reload,
213229
loadMore,
214230
}),
215231
[
232+
initialData,
216233
isIdle,
217234
isLoading,
218235
isSuccess,
@@ -221,7 +238,6 @@ export const useInfiniteDataLoader = <
221238
isLoadingFirstPage,
222239
reload,
223240
loadMore,
224-
initialData,
225241
],
226242
)
227243

0 commit comments

Comments
 (0)
Please sign in to comment.