@trackunit/react-graphql-hooks 1.15.1 → 1.15.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs.js +51 -15
- package/index.esm.js +52 -16
- package/package.json +4 -4
package/index.cjs.js
CHANGED
|
@@ -220,13 +220,23 @@ const useStableVariablesWithAbort = (variables, skip = false) => {
|
|
|
220
220
|
setAbortController(new AbortController());
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
|
-
reactComponents.useWatch({
|
|
224
|
-
value: variables,
|
|
225
|
-
onChange: setStableVariables,
|
|
226
|
-
skip: !Boolean(variables),
|
|
227
|
-
});
|
|
228
223
|
return { stableVariables, abortController };
|
|
229
224
|
};
|
|
225
|
+
/**
|
|
226
|
+
* Extracts declared variable names from a GraphQL document so the hook
|
|
227
|
+
* only injects relay pagination variables the query actually accepts.
|
|
228
|
+
*/
|
|
229
|
+
const getQueryVariableNames = (document) => {
|
|
230
|
+
const definition = document.definitions[0];
|
|
231
|
+
if (definition === undefined || definition.kind !== "OperationDefinition") {
|
|
232
|
+
return new Set();
|
|
233
|
+
}
|
|
234
|
+
const varDefs = definition.variableDefinitions;
|
|
235
|
+
if (varDefs === undefined) {
|
|
236
|
+
return new Set();
|
|
237
|
+
}
|
|
238
|
+
return new Set(varDefs.map(v => v.variable.name.value));
|
|
239
|
+
};
|
|
230
240
|
/**
|
|
231
241
|
* `usePaginationQuery` fetches data from a GraphQL query with Relay-style cursor pagination.
|
|
232
242
|
* It manages page accumulation, loading state, and provides `pagination` controls (including `fetchNext`)
|
|
@@ -273,6 +283,7 @@ const useStableVariablesWithAbort = (variables, skip = false) => {
|
|
|
273
283
|
*/
|
|
274
284
|
const usePaginationQuery = (document, props) => {
|
|
275
285
|
const pageSize = props.pageSize ?? props.variables?.first ?? reactComponents.defaultPageSize;
|
|
286
|
+
const declaredVarNames = react.useMemo(() => getQueryVariableNames(document), [document]);
|
|
276
287
|
const { stableVariables, abortController } = useStableVariablesWithAbort(props.variables, props.skip);
|
|
277
288
|
const [state, dispatch] = react.useReducer(createPaginationReducer(), {
|
|
278
289
|
data: undefined,
|
|
@@ -306,8 +317,10 @@ const usePaginationQuery = (document, props) => {
|
|
|
306
317
|
onReset,
|
|
307
318
|
initialCursor: props.initialCursor,
|
|
308
319
|
});
|
|
320
|
+
const { skip: _skip, updateQuery: _uq, pageSize: _ps, initialCursor: _ic, variables: _vars, ...lazyQueryProps } = props;
|
|
321
|
+
const networkStatusRef = react.useRef(0);
|
|
309
322
|
const [, { previousData, fetchMore, networkStatus, loading: lazyLoading }] = useLazyQuery(document, {
|
|
310
|
-
...
|
|
323
|
+
...lazyQueryProps,
|
|
311
324
|
variables: stableVariables !== undefined
|
|
312
325
|
? {
|
|
313
326
|
...stableVariables,
|
|
@@ -324,16 +337,19 @@ const usePaginationQuery = (document, props) => {
|
|
|
324
337
|
},
|
|
325
338
|
notifyOnNetworkStatusChange: true,
|
|
326
339
|
onCompleted: completedData => {
|
|
327
|
-
if (
|
|
340
|
+
if (networkStatusRef.current === client.NetworkStatus.refetch) {
|
|
328
341
|
dispatch({ type: "INCREMENT_RESET_TRIGGER" });
|
|
329
342
|
}
|
|
330
343
|
onCompletedRef.current?.(completedData);
|
|
331
|
-
},
|
|
332
|
-
//
|
|
333
|
-
|
|
334
|
-
nextFetchPolicy: "
|
|
335
|
-
initialFetchPolicy: "
|
|
344
|
+
},
|
|
345
|
+
// This is safe since we have no cache and want to control fetch outselves
|
|
346
|
+
fetchPolicy: "standby",
|
|
347
|
+
nextFetchPolicy: "standby",
|
|
348
|
+
initialFetchPolicy: "standby",
|
|
336
349
|
});
|
|
350
|
+
react.useEffect(() => {
|
|
351
|
+
networkStatusRef.current = networkStatus;
|
|
352
|
+
}, [networkStatus]);
|
|
337
353
|
const executeFetch = react.useCallback((variables, prev, direction) => {
|
|
338
354
|
if (props.skip) {
|
|
339
355
|
if (props.initialCursor === undefined) {
|
|
@@ -343,7 +359,8 @@ const usePaginationQuery = (document, props) => {
|
|
|
343
359
|
}
|
|
344
360
|
setIsLoading(true);
|
|
345
361
|
const signal = abortController.signal;
|
|
346
|
-
const
|
|
362
|
+
const filteredRelayVars = Object.fromEntries(Object.entries(variables).filter(([key]) => declaredVarNames.has(key)));
|
|
363
|
+
const fetchMoreVariables = { ...stableVariables, ...filteredRelayVars };
|
|
347
364
|
fetchMore({
|
|
348
365
|
variables: fetchMoreVariables,
|
|
349
366
|
updateQuery: createUpdateQueryHandler({
|
|
@@ -388,7 +405,16 @@ const usePaginationQuery = (document, props) => {
|
|
|
388
405
|
}
|
|
389
406
|
throw error;
|
|
390
407
|
});
|
|
391
|
-
}, [
|
|
408
|
+
}, [
|
|
409
|
+
props.skip,
|
|
410
|
+
props.initialCursor,
|
|
411
|
+
stableVariables,
|
|
412
|
+
setIsLoading,
|
|
413
|
+
fetchMore,
|
|
414
|
+
abortController,
|
|
415
|
+
setPageInfo,
|
|
416
|
+
declaredVarNames,
|
|
417
|
+
]);
|
|
392
418
|
// Single ref for values that effects need without triggering re-runs.
|
|
393
419
|
// Defined after executeFetch so it can be initialized with the real value.
|
|
394
420
|
const latestRef = react.useRef({
|
|
@@ -410,15 +436,25 @@ const usePaginationQuery = (document, props) => {
|
|
|
410
436
|
});
|
|
411
437
|
// Reset accumulated data when variables change (skip until first load
|
|
412
438
|
// to preserve initialCursor)
|
|
439
|
+
const pendingResetRef = react.useRef(false);
|
|
413
440
|
react.useEffect(() => {
|
|
414
441
|
if (!hasLoadedDataRef.current) {
|
|
415
442
|
return;
|
|
416
443
|
}
|
|
444
|
+
pendingResetRef.current = true;
|
|
417
445
|
dispatch({ type: "RESET" });
|
|
418
446
|
reset();
|
|
419
447
|
}, [stableVariables, reset]);
|
|
420
|
-
// Fetch initial page when variables or reset trigger changes
|
|
448
|
+
// Fetch initial page when variables or reset trigger changes.
|
|
449
|
+
// When stableVariables changes after data is loaded, the reset effect above
|
|
450
|
+
// also increments resetTrigger — which would cause this effect to fire twice.
|
|
451
|
+
// The pendingReset guard skips the first (stableVariables-triggered) fire so
|
|
452
|
+
// only the resetTrigger-triggered fire fetches.
|
|
421
453
|
react.useEffect(() => {
|
|
454
|
+
if (pendingResetRef.current) {
|
|
455
|
+
pendingResetRef.current = false;
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
422
458
|
const fetchVariables = {
|
|
423
459
|
first: latestRef.current.first ?? pageSize,
|
|
424
460
|
last: undefined,
|
package/index.esm.js
CHANGED
|
@@ -3,7 +3,7 @@ import { registerTranslations } from '@trackunit/i18n-library-translation';
|
|
|
3
3
|
import { useLazyQuery as useLazyQuery$1, NetworkStatus, useQuery as useQuery$1 } from '@apollo/client';
|
|
4
4
|
import { omit, isEqual } from 'es-toolkit';
|
|
5
5
|
import { useMemo, useReducer, useRef, useEffect, useCallback, useState } from 'react';
|
|
6
|
-
import { defaultPageSize, useRelayPagination
|
|
6
|
+
import { defaultPageSize, useRelayPagination } from '@trackunit/react-components';
|
|
7
7
|
import { truthy, objectKeys } from '@trackunit/shared-utils';
|
|
8
8
|
|
|
9
9
|
var defaultTranslations = {
|
|
@@ -218,13 +218,23 @@ const useStableVariablesWithAbort = (variables, skip = false) => {
|
|
|
218
218
|
setAbortController(new AbortController());
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
|
-
useWatch({
|
|
222
|
-
value: variables,
|
|
223
|
-
onChange: setStableVariables,
|
|
224
|
-
skip: !Boolean(variables),
|
|
225
|
-
});
|
|
226
221
|
return { stableVariables, abortController };
|
|
227
222
|
};
|
|
223
|
+
/**
|
|
224
|
+
* Extracts declared variable names from a GraphQL document so the hook
|
|
225
|
+
* only injects relay pagination variables the query actually accepts.
|
|
226
|
+
*/
|
|
227
|
+
const getQueryVariableNames = (document) => {
|
|
228
|
+
const definition = document.definitions[0];
|
|
229
|
+
if (definition === undefined || definition.kind !== "OperationDefinition") {
|
|
230
|
+
return new Set();
|
|
231
|
+
}
|
|
232
|
+
const varDefs = definition.variableDefinitions;
|
|
233
|
+
if (varDefs === undefined) {
|
|
234
|
+
return new Set();
|
|
235
|
+
}
|
|
236
|
+
return new Set(varDefs.map(v => v.variable.name.value));
|
|
237
|
+
};
|
|
228
238
|
/**
|
|
229
239
|
* `usePaginationQuery` fetches data from a GraphQL query with Relay-style cursor pagination.
|
|
230
240
|
* It manages page accumulation, loading state, and provides `pagination` controls (including `fetchNext`)
|
|
@@ -271,6 +281,7 @@ const useStableVariablesWithAbort = (variables, skip = false) => {
|
|
|
271
281
|
*/
|
|
272
282
|
const usePaginationQuery = (document, props) => {
|
|
273
283
|
const pageSize = props.pageSize ?? props.variables?.first ?? defaultPageSize;
|
|
284
|
+
const declaredVarNames = useMemo(() => getQueryVariableNames(document), [document]);
|
|
274
285
|
const { stableVariables, abortController } = useStableVariablesWithAbort(props.variables, props.skip);
|
|
275
286
|
const [state, dispatch] = useReducer(createPaginationReducer(), {
|
|
276
287
|
data: undefined,
|
|
@@ -304,8 +315,10 @@ const usePaginationQuery = (document, props) => {
|
|
|
304
315
|
onReset,
|
|
305
316
|
initialCursor: props.initialCursor,
|
|
306
317
|
});
|
|
318
|
+
const { skip: _skip, updateQuery: _uq, pageSize: _ps, initialCursor: _ic, variables: _vars, ...lazyQueryProps } = props;
|
|
319
|
+
const networkStatusRef = useRef(0);
|
|
307
320
|
const [, { previousData, fetchMore, networkStatus, loading: lazyLoading }] = useLazyQuery(document, {
|
|
308
|
-
...
|
|
321
|
+
...lazyQueryProps,
|
|
309
322
|
variables: stableVariables !== undefined
|
|
310
323
|
? {
|
|
311
324
|
...stableVariables,
|
|
@@ -322,16 +335,19 @@ const usePaginationQuery = (document, props) => {
|
|
|
322
335
|
},
|
|
323
336
|
notifyOnNetworkStatusChange: true,
|
|
324
337
|
onCompleted: completedData => {
|
|
325
|
-
if (
|
|
338
|
+
if (networkStatusRef.current === NetworkStatus.refetch) {
|
|
326
339
|
dispatch({ type: "INCREMENT_RESET_TRIGGER" });
|
|
327
340
|
}
|
|
328
341
|
onCompletedRef.current?.(completedData);
|
|
329
|
-
},
|
|
330
|
-
//
|
|
331
|
-
|
|
332
|
-
nextFetchPolicy: "
|
|
333
|
-
initialFetchPolicy: "
|
|
342
|
+
},
|
|
343
|
+
// This is safe since we have no cache and want to control fetch outselves
|
|
344
|
+
fetchPolicy: "standby",
|
|
345
|
+
nextFetchPolicy: "standby",
|
|
346
|
+
initialFetchPolicy: "standby",
|
|
334
347
|
});
|
|
348
|
+
useEffect(() => {
|
|
349
|
+
networkStatusRef.current = networkStatus;
|
|
350
|
+
}, [networkStatus]);
|
|
335
351
|
const executeFetch = useCallback((variables, prev, direction) => {
|
|
336
352
|
if (props.skip) {
|
|
337
353
|
if (props.initialCursor === undefined) {
|
|
@@ -341,7 +357,8 @@ const usePaginationQuery = (document, props) => {
|
|
|
341
357
|
}
|
|
342
358
|
setIsLoading(true);
|
|
343
359
|
const signal = abortController.signal;
|
|
344
|
-
const
|
|
360
|
+
const filteredRelayVars = Object.fromEntries(Object.entries(variables).filter(([key]) => declaredVarNames.has(key)));
|
|
361
|
+
const fetchMoreVariables = { ...stableVariables, ...filteredRelayVars };
|
|
345
362
|
fetchMore({
|
|
346
363
|
variables: fetchMoreVariables,
|
|
347
364
|
updateQuery: createUpdateQueryHandler({
|
|
@@ -386,7 +403,16 @@ const usePaginationQuery = (document, props) => {
|
|
|
386
403
|
}
|
|
387
404
|
throw error;
|
|
388
405
|
});
|
|
389
|
-
}, [
|
|
406
|
+
}, [
|
|
407
|
+
props.skip,
|
|
408
|
+
props.initialCursor,
|
|
409
|
+
stableVariables,
|
|
410
|
+
setIsLoading,
|
|
411
|
+
fetchMore,
|
|
412
|
+
abortController,
|
|
413
|
+
setPageInfo,
|
|
414
|
+
declaredVarNames,
|
|
415
|
+
]);
|
|
390
416
|
// Single ref for values that effects need without triggering re-runs.
|
|
391
417
|
// Defined after executeFetch so it can be initialized with the real value.
|
|
392
418
|
const latestRef = useRef({
|
|
@@ -408,15 +434,25 @@ const usePaginationQuery = (document, props) => {
|
|
|
408
434
|
});
|
|
409
435
|
// Reset accumulated data when variables change (skip until first load
|
|
410
436
|
// to preserve initialCursor)
|
|
437
|
+
const pendingResetRef = useRef(false);
|
|
411
438
|
useEffect(() => {
|
|
412
439
|
if (!hasLoadedDataRef.current) {
|
|
413
440
|
return;
|
|
414
441
|
}
|
|
442
|
+
pendingResetRef.current = true;
|
|
415
443
|
dispatch({ type: "RESET" });
|
|
416
444
|
reset();
|
|
417
445
|
}, [stableVariables, reset]);
|
|
418
|
-
// Fetch initial page when variables or reset trigger changes
|
|
446
|
+
// Fetch initial page when variables or reset trigger changes.
|
|
447
|
+
// When stableVariables changes after data is loaded, the reset effect above
|
|
448
|
+
// also increments resetTrigger — which would cause this effect to fire twice.
|
|
449
|
+
// The pendingReset guard skips the first (stableVariables-triggered) fire so
|
|
450
|
+
// only the resetTrigger-triggered fire fetches.
|
|
419
451
|
useEffect(() => {
|
|
452
|
+
if (pendingResetRef.current) {
|
|
453
|
+
pendingResetRef.current = false;
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
420
456
|
const fetchVariables = {
|
|
421
457
|
first: latestRef.current.first ?? pageSize,
|
|
422
458
|
last: undefined,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-graphql-hooks",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.6",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@apollo/client": "3.13.8",
|
|
11
11
|
"react": "19.0.0",
|
|
12
|
-
"@trackunit/i18n-library-translation": "1.12.
|
|
13
|
-
"@trackunit/shared-utils": "1.13.
|
|
12
|
+
"@trackunit/i18n-library-translation": "1.12.54",
|
|
13
|
+
"@trackunit/shared-utils": "1.13.63",
|
|
14
14
|
"es-toolkit": "^1.39.10",
|
|
15
|
-
"@trackunit/react-components": "1.18.
|
|
15
|
+
"@trackunit/react-components": "1.18.3"
|
|
16
16
|
},
|
|
17
17
|
"module": "./index.esm.js",
|
|
18
18
|
"main": "./index.cjs.js",
|